]> asedeno.scripts.mit.edu Git - linux.git/blob - kernel/irq/devres.c
irqdesc: Add a resource managed version of irq_alloc_descs()
[linux.git] / kernel / irq / devres.c
1 #include <linux/module.h>
2 #include <linux/interrupt.h>
3 #include <linux/device.h>
4 #include <linux/gfp.h>
5 #include <linux/irq.h>
6
7 /*
8  * Device resource management aware IRQ request/free implementation.
9  */
10 struct irq_devres {
11         unsigned int irq;
12         void *dev_id;
13 };
14
15 static void devm_irq_release(struct device *dev, void *res)
16 {
17         struct irq_devres *this = res;
18
19         free_irq(this->irq, this->dev_id);
20 }
21
22 static int devm_irq_match(struct device *dev, void *res, void *data)
23 {
24         struct irq_devres *this = res, *match = data;
25
26         return this->irq == match->irq && this->dev_id == match->dev_id;
27 }
28
29 /**
30  *      devm_request_threaded_irq - allocate an interrupt line for a managed device
31  *      @dev: device to request interrupt for
32  *      @irq: Interrupt line to allocate
33  *      @handler: Function to be called when the IRQ occurs
34  *      @thread_fn: function to be called in a threaded interrupt context. NULL
35  *                  for devices which handle everything in @handler
36  *      @irqflags: Interrupt type flags
37  *      @devname: An ascii name for the claiming device
38  *      @dev_id: A cookie passed back to the handler function
39  *
40  *      Except for the extra @dev argument, this function takes the
41  *      same arguments and performs the same function as
42  *      request_threaded_irq().  IRQs requested with this function will be
43  *      automatically freed on driver detach.
44  *
45  *      If an IRQ allocated with this function needs to be freed
46  *      separately, devm_free_irq() must be used.
47  */
48 int devm_request_threaded_irq(struct device *dev, unsigned int irq,
49                               irq_handler_t handler, irq_handler_t thread_fn,
50                               unsigned long irqflags, const char *devname,
51                               void *dev_id)
52 {
53         struct irq_devres *dr;
54         int rc;
55
56         dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
57                           GFP_KERNEL);
58         if (!dr)
59                 return -ENOMEM;
60
61         rc = request_threaded_irq(irq, handler, thread_fn, irqflags, devname,
62                                   dev_id);
63         if (rc) {
64                 devres_free(dr);
65                 return rc;
66         }
67
68         dr->irq = irq;
69         dr->dev_id = dev_id;
70         devres_add(dev, dr);
71
72         return 0;
73 }
74 EXPORT_SYMBOL(devm_request_threaded_irq);
75
76 /**
77  *      devm_request_any_context_irq - allocate an interrupt line for a managed device
78  *      @dev: device to request interrupt for
79  *      @irq: Interrupt line to allocate
80  *      @handler: Function to be called when the IRQ occurs
81  *      @thread_fn: function to be called in a threaded interrupt context. NULL
82  *                  for devices which handle everything in @handler
83  *      @irqflags: Interrupt type flags
84  *      @devname: An ascii name for the claiming device
85  *      @dev_id: A cookie passed back to the handler function
86  *
87  *      Except for the extra @dev argument, this function takes the
88  *      same arguments and performs the same function as
89  *      request_any_context_irq().  IRQs requested with this function will be
90  *      automatically freed on driver detach.
91  *
92  *      If an IRQ allocated with this function needs to be freed
93  *      separately, devm_free_irq() must be used.
94  */
95 int devm_request_any_context_irq(struct device *dev, unsigned int irq,
96                               irq_handler_t handler, unsigned long irqflags,
97                               const char *devname, void *dev_id)
98 {
99         struct irq_devres *dr;
100         int rc;
101
102         dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
103                           GFP_KERNEL);
104         if (!dr)
105                 return -ENOMEM;
106
107         rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id);
108         if (rc < 0) {
109                 devres_free(dr);
110                 return rc;
111         }
112
113         dr->irq = irq;
114         dr->dev_id = dev_id;
115         devres_add(dev, dr);
116
117         return rc;
118 }
119 EXPORT_SYMBOL(devm_request_any_context_irq);
120
121 /**
122  *      devm_free_irq - free an interrupt
123  *      @dev: device to free interrupt for
124  *      @irq: Interrupt line to free
125  *      @dev_id: Device identity to free
126  *
127  *      Except for the extra @dev argument, this function takes the
128  *      same arguments and performs the same function as free_irq().
129  *      This function instead of free_irq() should be used to manually
130  *      free IRQs allocated with devm_request_irq().
131  */
132 void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
133 {
134         struct irq_devres match_data = { irq, dev_id };
135
136         WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
137                                &match_data));
138         free_irq(irq, dev_id);
139 }
140 EXPORT_SYMBOL(devm_free_irq);
141
142 struct irq_desc_devres {
143         unsigned int from;
144         unsigned int cnt;
145 };
146
147 static void devm_irq_desc_release(struct device *dev, void *res)
148 {
149         struct irq_desc_devres *this = res;
150
151         irq_free_descs(this->from, this->cnt);
152 }
153
154 /**
155  * __devm_irq_alloc_descs - Allocate and initialize a range of irq descriptors
156  *                          for a managed device
157  * @dev:        Device to allocate the descriptors for
158  * @irq:        Allocate for specific irq number if irq >= 0
159  * @from:       Start the search from this irq number
160  * @cnt:        Number of consecutive irqs to allocate
161  * @node:       Preferred node on which the irq descriptor should be allocated
162  * @owner:      Owning module (can be NULL)
163  * @affinity:   Optional pointer to an affinity mask array of size @cnt
164  *              which hints where the irq descriptors should be allocated
165  *              and which default affinities to use
166  *
167  * Returns the first irq number or error code.
168  *
169  * Note: Use the provided wrappers (devm_irq_alloc_desc*) for simplicity.
170  */
171 int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
172                            unsigned int cnt, int node, struct module *owner,
173                            const struct cpumask *affinity)
174 {
175         struct irq_desc_devres *dr;
176         int base;
177
178         dr = devres_alloc(devm_irq_desc_release, sizeof(*dr), GFP_KERNEL);
179         if (!dr)
180                 return -ENOMEM;
181
182         base = __irq_alloc_descs(irq, from, cnt, node, owner, affinity);
183         if (base < 0) {
184                 devres_free(dr);
185                 return base;
186         }
187
188         dr->from = base;
189         dr->cnt = cnt;
190         devres_add(dev, dr);
191
192         return base;
193 }
194 EXPORT_SYMBOL_GPL(__devm_irq_alloc_descs);