Blame view

kernel/irq/chip.c 18.7 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
  #include <linux/module.h>
  #include <linux/interrupt.h>
  #include <linux/kernel_stat.h>
f069686e4   Steven Rostedt   tracing/softirq: ...
18
  #include <trace/events/irq.h>
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
19
  #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;
a09b659cd   Russell King   genirq: Fix long-...
62
  	ret = __irq_set_trigger(desc, irq, type);
02725e747   Thomas Gleixner   genirq: Use irq_g...
63
  	irq_put_desc_busunlock(desc, flags);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
64
65
  	return ret;
  }
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
66
  EXPORT_SYMBOL(irq_set_irq_type);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
67
68
  
  /**
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
69
   *	irq_set_handler_data - set irq handler data for an irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
70
71
72
73
74
   *	@irq:	Interrupt number
   *	@data:	Pointer to interrupt specific data
   *
   *	Set the hardware irq controller data for an irq
   */
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
75
  int irq_set_handler_data(unsigned int irq, void *data)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
76
  {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
77
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
78
  	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
79

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

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

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

f303a6dd1   Thomas Gleixner   genirq: Sanitize ...
129
130
131
132
133
134
135
  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_...
136
137
  static void irq_state_clr_disabled(struct irq_desc *desc)
  {
801a0e9ae   Thomas Gleixner   genirq: Add irq d...
138
  	irqd_clear(&desc->irq_data, IRQD_IRQ_DISABLED);
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
139
140
141
142
  }
  
  static void irq_state_set_disabled(struct irq_desc *desc)
  {
801a0e9ae   Thomas Gleixner   genirq: Add irq d...
143
  	irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
144
  }
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
145
146
  static void irq_state_clr_masked(struct irq_desc *desc)
  {
32f4125eb   Thomas Gleixner   genirq: Move INPR...
147
  	irqd_clear(&desc->irq_data, IRQD_IRQ_MASKED);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
148
149
150
151
  }
  
  static void irq_state_set_masked(struct irq_desc *desc)
  {
32f4125eb   Thomas Gleixner   genirq: Move INPR...
152
  	irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
153
  }
b4bc724e8   Thomas Gleixner   genirq: Handle pe...
154
  int irq_startup(struct irq_desc *desc, bool resend)
469992386   Thomas Gleixner   genirq: Consolida...
155
  {
b4bc724e8   Thomas Gleixner   genirq: Handle pe...
156
  	int ret = 0;
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
  	if (desc->irq_data.chip->irq_startup) {
b4bc724e8   Thomas Gleixner   genirq: Handle pe...
160
  		ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
161
  		irq_state_clr_masked(desc);
b4bc724e8   Thomas Gleixner   genirq: Handle pe...
162
163
  	} else {
  		irq_enable(desc);
3aae994fb   Thomas Gleixner   genirq: Consolida...
164
  	}
b4bc724e8   Thomas Gleixner   genirq: Handle pe...
165
166
167
  	if (resend)
  		check_irq_resend(desc, desc->irq_data.irq);
  	return ret;
469992386   Thomas Gleixner   genirq: Consolida...
168
169
170
171
  }
  
  void irq_shutdown(struct irq_desc *desc)
  {
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
172
  	irq_state_set_disabled(desc);
469992386   Thomas Gleixner   genirq: Consolida...
173
  	desc->depth = 1;
50f7c0327   Thomas Gleixner   genirq: Remove de...
174
175
  	if (desc->irq_data.chip->irq_shutdown)
  		desc->irq_data.chip->irq_shutdown(&desc->irq_data);
ed585a651   Geert Uytterhoeven   genirq: Make irq_...
176
  	else if (desc->irq_data.chip->irq_disable)
50f7c0327   Thomas Gleixner   genirq: Remove de...
177
178
179
  		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_...
180
  	irq_state_set_masked(desc);
469992386   Thomas Gleixner   genirq: Consolida...
181
  }
87923470c   Thomas Gleixner   genirq: Consolida...
182
183
  void irq_enable(struct irq_desc *desc)
  {
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
184
  	irq_state_clr_disabled(desc);
50f7c0327   Thomas Gleixner   genirq: Remove de...
185
186
187
188
  	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_...
189
  	irq_state_clr_masked(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
190
  }
50f7c0327   Thomas Gleixner   genirq: Remove de...
191
  void irq_disable(struct irq_desc *desc)
89d694b9d   Thomas Gleixner   genirq: do not le...
192
  {
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
193
  	irq_state_set_disabled(desc);
50f7c0327   Thomas Gleixner   genirq: Remove de...
194
195
  	if (desc->irq_data.chip->irq_disable) {
  		desc->irq_data.chip->irq_disable(&desc->irq_data);
a61d82580   Thomas Gleixner   genirq: Fix mispl...
196
  		irq_state_set_masked(desc);
50f7c0327   Thomas Gleixner   genirq: Remove de...
197
  	}
89d694b9d   Thomas Gleixner   genirq: do not le...
198
  }
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  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...
216
  static inline void mask_ack_irq(struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
217
  {
9205e31d1   Thomas Gleixner   genirq: Provide c...
218
219
  	if (desc->irq_data.chip->irq_mask_ack)
  		desc->irq_data.chip->irq_mask_ack(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
220
  	else {
e2c0f8ff0   Thomas Gleixner   genirq: Provide c...
221
  		desc->irq_data.chip->irq_mask(&desc->irq_data);
22a49163e   Thomas Gleixner   genirq: Provide c...
222
223
  		if (desc->irq_data.chip->irq_ack)
  			desc->irq_data.chip->irq_ack(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
224
  	}
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
225
  	irq_state_set_masked(desc);
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
226
  }
d4d5e0896   Thomas Gleixner   genirq: Add IRQCH...
227
  void mask_irq(struct irq_desc *desc)
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
228
  {
e2c0f8ff0   Thomas Gleixner   genirq: Provide c...
229
230
  	if (desc->irq_data.chip->irq_mask) {
  		desc->irq_data.chip->irq_mask(&desc->irq_data);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
231
  		irq_state_set_masked(desc);
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
232
233
  	}
  }
d4d5e0896   Thomas Gleixner   genirq: Add IRQCH...
234
  void unmask_irq(struct irq_desc *desc)
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
235
  {
0eda58b7f   Thomas Gleixner   genirq: Provide c...
236
237
  	if (desc->irq_data.chip->irq_unmask) {
  		desc->irq_data.chip->irq_unmask(&desc->irq_data);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
238
  		irq_state_clr_masked(desc);
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
239
  	}
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
240
  }
399b5da29   Thomas Gleixner   genirq: Support n...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
  /*
   *	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...
256
  	raw_spin_lock_irq(&desc->lock);
399b5da29   Thomas Gleixner   genirq: Support n...
257
258
259
260
  
  	kstat_incr_irqs_this_cpu(irq, desc);
  
  	action = desc->action;
23812b9d9   Ning Jiang   genirq: Add IRQS_...
261
262
  	if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) {
  		desc->istate |= IRQS_PENDING;
399b5da29   Thomas Gleixner   genirq: Support n...
263
  		goto out_unlock;
23812b9d9   Ning Jiang   genirq: Add IRQS_...
264
  	}
399b5da29   Thomas Gleixner   genirq: Support n...
265

32f4125eb   Thomas Gleixner   genirq: Move INPR...
266
  	irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
239007b84   Thomas Gleixner   genirq: Convert i...
267
  	raw_spin_unlock_irq(&desc->lock);
399b5da29   Thomas Gleixner   genirq: Support n...
268
269
270
271
  
  	action_ret = action->thread_fn(action->irq, action->dev_id);
  	if (!noirqdebug)
  		note_interrupt(irq, desc, action_ret);
239007b84   Thomas Gleixner   genirq: Convert i...
272
  	raw_spin_lock_irq(&desc->lock);
32f4125eb   Thomas Gleixner   genirq: Move INPR...
273
  	irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
399b5da29   Thomas Gleixner   genirq: Support n...
274
275
  
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
276
  	raw_spin_unlock_irq(&desc->lock);
399b5da29   Thomas Gleixner   genirq: Support n...
277
278
  }
  EXPORT_SYMBOL_GPL(handle_nested_irq);
fe200ae48   Thomas Gleixner   genirq: Mark poll...
279
280
  static bool irq_check_poll(struct irq_desc *desc)
  {
6954b75b4   Thomas Gleixner   genirq: Move IRQ_...
281
  	if (!(desc->istate & IRQS_POLL_INPROGRESS))
fe200ae48   Thomas Gleixner   genirq: Mark poll...
282
283
284
  		return false;
  	return irq_wait_for_poll(desc);
  }
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
285
286
287
288
  /**
   *	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...
289
290
291
292
293
294
295
296
   *
   *	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...
297
  void
7d12e780e   David Howells   IRQ: Maintain reg...
298
  handle_simple_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
299
  {
239007b84   Thomas Gleixner   genirq: Convert i...
300
  	raw_spin_lock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
301

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

23812b9d9   Ning Jiang   genirq: Add IRQS_...
308
309
  	if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
  		desc->istate |= IRQS_PENDING;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
310
  		goto out_unlock;
23812b9d9   Ning Jiang   genirq: Add IRQS_...
311
  	}
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
312

107781e72   Thomas Gleixner   genirq: Use handl...
313
  	handle_irq_event(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
314

dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
315
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
316
  	raw_spin_unlock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
317
  }
edf76f830   Jonathan Cameron   irq: Export funct...
318
  EXPORT_SYMBOL_GPL(handle_simple_irq);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
319

ac5637611   Thomas Gleixner   genirq: Unmask on...
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  /*
   * Called unconditionally from handle_level_irq() and only for oneshot
   * interrupts from handle_fasteoi_irq()
   */
  static void cond_unmask_irq(struct irq_desc *desc)
  {
  	/*
  	 * We need to unmask in the following cases:
  	 * - Standard level irq (IRQF_ONESHOT is not set)
  	 * - Oneshot irq which did not wake the thread (caused by a
  	 *   spurious interrupt or a primary handler handling it
  	 *   completely).
  	 */
  	if (!irqd_irq_disabled(&desc->irq_data) &&
  	    irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot)
  		unmask_irq(desc);
  }
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
337
338
339
340
  /**
   *	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...
341
342
343
344
345
346
   *
   *	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...
347
  void
7d12e780e   David Howells   IRQ: Maintain reg...
348
  handle_level_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
349
  {
239007b84   Thomas Gleixner   genirq: Convert i...
350
  	raw_spin_lock(&desc->lock);
9205e31d1   Thomas Gleixner   genirq: Provide c...
351
  	mask_ack_irq(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
352

32f4125eb   Thomas Gleixner   genirq: Move INPR...
353
  	if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
fe200ae48   Thomas Gleixner   genirq: Mark poll...
354
355
  		if (!irq_check_poll(desc))
  			goto out_unlock;
163ef3091   Thomas Gleixner   genirq: Move IRQ_...
356
  	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
d6c88a507   Thomas Gleixner   genirq: revert dy...
357
  	kstat_incr_irqs_this_cpu(irq, desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
358
359
360
361
362
  
  	/*
  	 * If its disabled or no action available
  	 * keep it masked and get out of here
  	 */
d4dc0f90d   Thomas Gleixner   genirq: Allow che...
363
364
  	if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
  		desc->istate |= IRQS_PENDING;
86998aa65   Ingo Molnar   [PATCH] genirq co...
365
  		goto out_unlock;
d4dc0f90d   Thomas Gleixner   genirq: Allow che...
366
  	}
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
367

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

ac5637611   Thomas Gleixner   genirq: Unmask on...
370
  	cond_unmask_irq(desc);
86998aa65   Ingo Molnar   [PATCH] genirq co...
371
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
372
  	raw_spin_unlock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
373
  }
14819ea1e   Ingo Molnar   irq: export __set...
374
  EXPORT_SYMBOL_GPL(handle_level_irq);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
375

781295762   Thomas Gleixner   genirq: Add prefl...
376
377
378
379
380
381
382
383
384
  #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...
385
  /**
47c2a3aa4   Ingo Molnar   [PATCH] genirq: a...
386
   *	handle_fasteoi_irq - irq handler for transparent controllers
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
387
388
   *	@irq:	the interrupt number
   *	@desc:	the interrupt description structure for this irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
389
   *
47c2a3aa4   Ingo Molnar   [PATCH] genirq: a...
390
   *	Only a single callback will be issued to the chip: an ->eoi()
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
391
392
393
394
   *	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...
395
  void
7d12e780e   David Howells   IRQ: Maintain reg...
396
  handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
397
  {
239007b84   Thomas Gleixner   genirq: Convert i...
398
  	raw_spin_lock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
399

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

163ef3091   Thomas Gleixner   genirq: Move IRQ_...
404
  	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
d6c88a507   Thomas Gleixner   genirq: revert dy...
405
  	kstat_incr_irqs_this_cpu(irq, desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
406
407
408
  
  	/*
  	 * If its disabled or no action available
76d216014   Ingo Molnar   [PATCH] genirq: d...
409
  	 * then mask it and get out of here:
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
410
  	 */
32f4125eb   Thomas Gleixner   genirq: Move INPR...
411
  	if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
2a0d6fb33   Thomas Gleixner   genirq: Move IRQ_...
412
  		desc->istate |= IRQS_PENDING;
e2c0f8ff0   Thomas Gleixner   genirq: Provide c...
413
  		mask_irq(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
414
  		goto out;
98bb244b6   Benjamin Herrenschmidt   [PATCH] genirq: f...
415
  	}
c69e3758f   Thomas Gleixner   genirq: Fixup fas...
416
417
418
  
  	if (desc->istate & IRQS_ONESHOT)
  		mask_irq(desc);
781295762   Thomas Gleixner   genirq: Add prefl...
419
  	preflow_handler(desc);
a7ae4de5c   Thomas Gleixner   genirq: Use handl...
420
  	handle_irq_event(desc);
77694b408   Thomas Gleixner   genirq; Add faste...
421

ac5637611   Thomas Gleixner   genirq: Unmask on...
422
423
  	if (desc->istate & IRQS_ONESHOT)
  		cond_unmask_irq(desc);
77694b408   Thomas Gleixner   genirq; Add faste...
424
  out_eoi:
0c5c15572   Thomas Gleixner   genirq: Provide c...
425
  	desc->irq_data.chip->irq_eoi(&desc->irq_data);
77694b408   Thomas Gleixner   genirq; Add faste...
426
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
427
  	raw_spin_unlock(&desc->lock);
77694b408   Thomas Gleixner   genirq; Add faste...
428
429
430
431
432
  	return;
  out:
  	if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED))
  		goto out_eoi;
  	goto out_unlock;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
433
434
435
436
437
438
  }
  
  /**
   *	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...
439
440
   *
   *	Interrupt occures on the falling and/or rising edge of a hardware
25985edce   Lucas De Marchi   Fix common misspe...
441
   *	signal. The occurrence is latched into the irq controller hardware
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
442
443
   *	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...
444
   *	is handled by the associated event handler. If this happens it
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
445
446
447
448
449
450
   *	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...
451
  void
7d12e780e   David Howells   IRQ: Maintain reg...
452
  handle_edge_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
453
  {
239007b84   Thomas Gleixner   genirq: Convert i...
454
  	raw_spin_lock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
455

163ef3091   Thomas Gleixner   genirq: Move IRQ_...
456
  	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
457
458
459
460
461
  	/*
  	 * 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...
462
463
  	if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
  		     irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
fe200ae48   Thomas Gleixner   genirq: Mark poll...
464
  		if (!irq_check_poll(desc)) {
2a0d6fb33   Thomas Gleixner   genirq: Move IRQ_...
465
  			desc->istate |= IRQS_PENDING;
fe200ae48   Thomas Gleixner   genirq: Mark poll...
466
467
468
  			mask_ack_irq(desc);
  			goto out_unlock;
  		}
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
469
  	}
d6c88a507   Thomas Gleixner   genirq: revert dy...
470
  	kstat_incr_irqs_this_cpu(irq, desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
471
472
  
  	/* Start handling the irq */
22a49163e   Thomas Gleixner   genirq: Provide c...
473
  	desc->irq_data.chip->irq_ack(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
474

dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
475
  	do {
a60a5dc2d   Thomas Gleixner   genirq: Use handl...
476
  		if (unlikely(!desc->action)) {
e2c0f8ff0   Thomas Gleixner   genirq: Provide c...
477
  			mask_irq(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
478
479
480
481
482
483
484
485
  			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_...
486
  		if (unlikely(desc->istate & IRQS_PENDING)) {
32f4125eb   Thomas Gleixner   genirq: Move INPR...
487
488
  			if (!irqd_irq_disabled(&desc->irq_data) &&
  			    irqd_irq_masked(&desc->irq_data))
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
489
  				unmask_irq(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
490
  		}
a60a5dc2d   Thomas Gleixner   genirq: Use handl...
491
  		handle_irq_event(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
492

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

dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
496
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
497
  	raw_spin_unlock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
498
  }
3911ff30f   Jiri Kosina   genirq: export ha...
499
  EXPORT_SYMBOL(handle_edge_irq);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
500

0521c8fbb   Thomas Gleixner   genirq: Provide e...
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  #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...
539
  out_eoi:
0521c8fbb   Thomas Gleixner   genirq: Provide e...
540
541
542
543
  	chip->irq_eoi(&desc->irq_data);
  	raw_spin_unlock(&desc->lock);
  }
  #endif
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
544
  /**
24b26d421   Liuweni   irq: Fix docbook ...
545
   *	handle_percpu_irq - Per CPU local irq handler
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
546
547
   *	@irq:	the interrupt number
   *	@desc:	the interrupt description structure for this irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
548
549
550
   *
   *	Per CPU interrupts on SMP machines without locking requirements
   */
7ad5b3a50   Harvey Harrison   kernel: remove fa...
551
  void
7d12e780e   David Howells   IRQ: Maintain reg...
552
  handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
553
  {
35e857cbe   Thomas Gleixner   genirq: Fixup cor...
554
  	struct irq_chip *chip = irq_desc_get_chip(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
555

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

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

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

849f061c2   Thomas Gleixner   genirq: Use handl...
563
564
  	if (chip->irq_eoi)
  		chip->irq_eoi(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
565
  }
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
  /**
   * 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...
597
  void
3836ca08a   Thomas Gleixner   genirq: Consolida...
598
  __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
a460e745e   Ingo Molnar   [PATCH] genirq: c...
599
  		  const char *name)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
600
  {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
601
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
602
  	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
603

02725e747   Thomas Gleixner   genirq: Use irq_g...
604
  	if (!desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
605
  		return;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
606

091738a26   Thomas Gleixner   genirq: Remove re...
607
  	if (!handle) {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
608
  		handle = handle_bad_irq;
091738a26   Thomas Gleixner   genirq: Remove re...
609
610
  	} else {
  		if (WARN_ON(desc->irq_data.chip == &no_irq_chip))
02725e747   Thomas Gleixner   genirq: Use irq_g...
611
  			goto out;
f8b5473fc   Thomas Gleixner   [ARM] 3690/1: gen...
612
  	}
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
613

dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
614
615
  	/* Uninstall? */
  	if (handle == handle_bad_irq) {
6b8ff3120   Thomas Gleixner   genirq: Convert c...
616
  		if (desc->irq_data.chip != &no_irq_chip)
9205e31d1   Thomas Gleixner   genirq: Provide c...
617
  			mask_ack_irq(desc);
801a0e9ae   Thomas Gleixner   genirq: Add irq d...
618
  		irq_state_set_disabled(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
619
620
621
  		desc->depth = 1;
  	}
  	desc->handle_irq = handle;
a460e745e   Ingo Molnar   [PATCH] genirq: c...
622
  	desc->name = name;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
623
624
  
  	if (handle != handle_bad_irq && is_chained) {
1ccb4e612   Thomas Gleixner   genirq: Wrap the ...
625
626
  		irq_settings_set_noprobe(desc);
  		irq_settings_set_norequest(desc);
7f1b1244e   Paul Mundt   genirq: Support p...
627
  		irq_settings_set_nothread(desc);
b4bc724e8   Thomas Gleixner   genirq: Handle pe...
628
  		irq_startup(desc, true);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
629
  	}
02725e747   Thomas Gleixner   genirq: Use irq_g...
630
631
  out:
  	irq_put_desc_busunlock(desc, flags);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
632
  }
3836ca08a   Thomas Gleixner   genirq: Consolida...
633
  EXPORT_SYMBOL_GPL(__irq_set_handler);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
634
635
  
  void
3836ca08a   Thomas Gleixner   genirq: Consolida...
636
  irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
a460e745e   Ingo Molnar   [PATCH] genirq: c...
637
  			      irq_flow_handler_t handle, const char *name)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
638
  {
35e857cbe   Thomas Gleixner   genirq: Fixup cor...
639
  	irq_set_chip(irq, chip);
3836ca08a   Thomas Gleixner   genirq: Consolida...
640
  	__irq_set_handler(irq, handle, 0, name);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
641
  }
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
642

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

442471848   Thomas Gleixner   genirq: Provide s...
648
  	if (!desc)
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
649
  		return;
a005677b3   Thomas Gleixner   genirq: Mirror IR...
650
  	irq_settings_clr_and_set(desc, clr, set);
876dbd4cc   Thomas Gleixner   genirq: Mirror ir...
651
  	irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU |
e1ef82414   Thomas Gleixner   genirq: Reflect I...
652
  		   IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT);
a005677b3   Thomas Gleixner   genirq: Mirror IR...
653
654
655
656
  	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...
657
658
  	if (irq_settings_can_move_pcntxt(desc))
  		irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT);
0ef5ca1e1   Thomas Gleixner   genirq; Fix clean...
659
660
  	if (irq_settings_is_level(desc))
  		irqd_set(&desc->irq_data, IRQD_LEVEL);
a005677b3   Thomas Gleixner   genirq: Mirror IR...
661

876dbd4cc   Thomas Gleixner   genirq: Mirror ir...
662
  	irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc));
02725e747   Thomas Gleixner   genirq: Use irq_g...
663
  	irq_put_desc_unlock(desc, flags);
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
664
  }
edf76f830   Jonathan Cameron   irq: Export funct...
665
  EXPORT_SYMBOL_GPL(irq_modify_status);
0fdb4b259   David Daney   genirq: Add chip ...
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
  
  /**
   *	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 ...
688
689
  		if (chip && chip->irq_cpu_online &&
  		    (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) ||
32f4125eb   Thomas Gleixner   genirq: Move INPR...
690
  		     !irqd_irq_disabled(&desc->irq_data)))
0fdb4b259   David Daney   genirq: Add chip ...
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
  			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 ...
718
719
  		if (chip && chip->irq_cpu_offline &&
  		    (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) ||
32f4125eb   Thomas Gleixner   genirq: Move INPR...
720
  		     !irqd_irq_disabled(&desc->irq_data)))
0fdb4b259   David Daney   genirq: Add chip ...
721
722
723
724
725
  			chip->irq_cpu_offline(&desc->irq_data);
  
  		raw_spin_unlock_irqrestore(&desc->lock, flags);
  	}
  }