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
99int devm_request_any_context_irq(struct device *dev, unsigned int irq,
100 irq_handler_t handler, unsigned long irqflags,
101 const char *devname, void *dev_id)
102{
103 struct irq_devres *dr;
104 int rc;
105
106 dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
107 GFP_KERNEL);
108 if (!dr)
109 return -ENOMEM;
110
111 if (!devname)
112 devname = dev_name(dev);
113
114 rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id);
115 if (rc < 0) {
116 devres_free(dr);
117 return rc;
118 }
119
120 dr->irq = irq;
121 dr->dev_id = dev_id;
122 devres_add(dev, dr);
123
124 return rc;
125}
126EXPORT_SYMBOL(devm_request_any_context_irq);
127
128
129
130
131
132
133
134
135
136
137
138
139void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
140{
141 struct irq_devres match_data = { irq, dev_id };
142
143 WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
144 &match_data));
145 free_irq(irq, dev_id);
146}
147EXPORT_SYMBOL(devm_free_irq);
148
149struct irq_desc_devres {
150 unsigned int from;
151 unsigned int cnt;
152};
153
154static void devm_irq_desc_release(struct device *dev, void *res)
155{
156 struct irq_desc_devres *this = res;
157
158 irq_free_descs(this->from, this->cnt);
159}
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
179 unsigned int cnt, int node, struct module *owner,
180 const struct irq_affinity_desc *affinity)
181{
182 struct irq_desc_devres *dr;
183 int base;
184
185 dr = devres_alloc(devm_irq_desc_release, sizeof(*dr), GFP_KERNEL);
186 if (!dr)
187 return -ENOMEM;
188
189 base = __irq_alloc_descs(irq, from, cnt, node, owner, affinity);
190 if (base < 0) {
191 devres_free(dr);
192 return base;
193 }
194
195 dr->from = base;
196 dr->cnt = cnt;
197 devres_add(dev, dr);
198
199 return base;
200}
201EXPORT_SYMBOL_GPL(__devm_irq_alloc_descs);
202
203#ifdef CONFIG_GENERIC_IRQ_CHIP
204
205
206
207
208
209
210
211
212
213
214
215
216
217struct irq_chip_generic *
218devm_irq_alloc_generic_chip(struct device *dev, const char *name, int num_ct,
219 unsigned int irq_base, void __iomem *reg_base,
220 irq_flow_handler_t handler)
221{
222 struct irq_chip_generic *gc;
223
224 gc = devm_kzalloc(dev, struct_size(gc, chip_types, num_ct), GFP_KERNEL);
225 if (gc)
226 irq_init_generic_chip(gc, name, num_ct,
227 irq_base, reg_base, handler);
228
229 return gc;
230}
231EXPORT_SYMBOL_GPL(devm_irq_alloc_generic_chip);
232
233struct irq_generic_chip_devres {
234 struct irq_chip_generic *gc;
235 u32 msk;
236 unsigned int clr;
237 unsigned int set;
238};
239
240static void devm_irq_remove_generic_chip(struct device *dev, void *res)
241{
242 struct irq_generic_chip_devres *this = res;
243
244 irq_remove_generic_chip(this->gc, this->msk, this->clr, this->set);
245}
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262int devm_irq_setup_generic_chip(struct device *dev, struct irq_chip_generic *gc,
263 u32 msk, enum irq_gc_flags flags,
264 unsigned int clr, unsigned int set)
265{
266 struct irq_generic_chip_devres *dr;
267
268 dr = devres_alloc(devm_irq_remove_generic_chip,
269 sizeof(*dr), GFP_KERNEL);
270 if (!dr)
271 return -ENOMEM;
272
273 irq_setup_generic_chip(gc, msk, flags, clr, set);
274
275 dr->gc = gc;
276 dr->msk = msk;
277 dr->clr = clr;
278 dr->set = set;
279 devres_add(dev, dr);
280
281 return 0;
282}
283EXPORT_SYMBOL_GPL(devm_irq_setup_generic_chip);
284#endif
285