1
2#include <linux/module.h>
3#include <linux/interrupt.h>
4#include <linux/device.h>
5#include <linux/gfp.h>
6#include <linux/irq.h>
7
8#include "internals.h"
9
10
11
12
13struct irq_devres {
14 unsigned int irq;
15 void *dev_id;
16};
17
18static void devm_irq_release(struct device *dev, void *res)
19{
20 struct irq_devres *this = res;
21
22 free_irq(this->irq, this->dev_id);
23}
24
25static int devm_irq_match(struct device *dev, void *res, void *data)
26{
27 struct irq_devres *this = res, *match = data;
28
29 return this->irq == match->irq && this->dev_id == match->dev_id;
30}
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51int devm_request_threaded_irq(struct device *dev, unsigned int irq,
52 irq_handler_t handler, irq_handler_t thread_fn,
53 unsigned long irqflags, const char *devname,
54 void *dev_id)
55{
56 struct irq_devres *dr;
57 int rc;
58
59 dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
60 GFP_KERNEL);
61 if (!dr)
62 return -ENOMEM;
63
64 if (!devname)
65 devname = dev_name(dev);
66
67 rc = request_threaded_irq(irq, handler, thread_fn, irqflags, devname,
68 dev_id);
69 if (rc) {
70 devres_free(dr);
71 return rc;
72 }
73
74 dr->irq = irq;
75 dr->dev_id = dev_id;
76 devres_add(dev, dr);
77
78 return 0;
79}
80EXPORT_SYMBOL(devm_request_threaded_irq);
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101int devm_request_any_context_irq(struct device *dev, unsigned int irq,
102 irq_handler_t handler, unsigned long irqflags,
103 const char *devname, void *dev_id)
104{
105 struct irq_devres *dr;
106 int rc;
107
108 dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
109 GFP_KERNEL);
110 if (!dr)
111 return -ENOMEM;
112
113 if (!devname)
114 devname = dev_name(dev);
115
116 rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id);
117 if (rc < 0) {
118 devres_free(dr);
119 return rc;
120 }
121
122 dr->irq = irq;
123 dr->dev_id = dev_id;
124 devres_add(dev, dr);
125
126 return rc;
127}
128EXPORT_SYMBOL(devm_request_any_context_irq);
129
130
131
132
133
134
135
136
137
138
139
140
141void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
142{
143 struct irq_devres match_data = { irq, dev_id };
144
145 WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
146 &match_data));
147 free_irq(irq, dev_id);
148}
149EXPORT_SYMBOL(devm_free_irq);
150
151struct irq_desc_devres {
152 unsigned int from;
153 unsigned int cnt;
154};
155
156static void devm_irq_desc_release(struct device *dev, void *res)
157{
158 struct irq_desc_devres *this = res;
159
160 irq_free_descs(this->from, this->cnt);
161}
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
181 unsigned int cnt, int node, struct module *owner,
182 const struct cpumask *affinity)
183{
184 struct irq_desc_devres *dr;
185 int base;
186
187 dr = devres_alloc(devm_irq_desc_release, sizeof(*dr), GFP_KERNEL);
188 if (!dr)
189 return -ENOMEM;
190
191 base = __irq_alloc_descs(irq, from, cnt, node, owner, affinity);
192 if (base < 0) {
193 devres_free(dr);
194 return base;
195 }
196
197 dr->from = base;
198 dr->cnt = cnt;
199 devres_add(dev, dr);
200
201 return base;
202}
203EXPORT_SYMBOL_GPL(__devm_irq_alloc_descs);
204
205#ifdef CONFIG_GENERIC_IRQ_CHIP
206
207
208
209
210
211
212
213
214
215
216
217
218
219struct irq_chip_generic *
220devm_irq_alloc_generic_chip(struct device *dev, const char *name, int num_ct,
221 unsigned int irq_base, void __iomem *reg_base,
222 irq_flow_handler_t handler)
223{
224 struct irq_chip_generic *gc;
225 unsigned long sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
226
227 gc = devm_kzalloc(dev, sz, GFP_KERNEL);
228 if (gc)
229 irq_init_generic_chip(gc, name, num_ct,
230 irq_base, reg_base, handler);
231
232 return gc;
233}
234EXPORT_SYMBOL_GPL(devm_irq_alloc_generic_chip);
235
236struct irq_generic_chip_devres {
237 struct irq_chip_generic *gc;
238 u32 msk;
239 unsigned int clr;
240 unsigned int set;
241};
242
243static void devm_irq_remove_generic_chip(struct device *dev, void *res)
244{
245 struct irq_generic_chip_devres *this = res;
246
247 irq_remove_generic_chip(this->gc, this->msk, this->clr, this->set);
248}
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265int devm_irq_setup_generic_chip(struct device *dev, struct irq_chip_generic *gc,
266 u32 msk, enum irq_gc_flags flags,
267 unsigned int clr, unsigned int set)
268{
269 struct irq_generic_chip_devres *dr;
270
271 dr = devres_alloc(devm_irq_remove_generic_chip,
272 sizeof(*dr), GFP_KERNEL);
273 if (!dr)
274 return -ENOMEM;
275
276 irq_setup_generic_chip(gc, msk, flags, clr, set);
277
278 dr->gc = gc;
279 dr->msk = msk;
280 dr->clr = clr;
281 dr->set = set;
282 devres_add(dev, dr);
283
284 return 0;
285}
286EXPORT_SYMBOL_GPL(devm_irq_setup_generic_chip);
287#endif
288