1 #include <linux/module.h> 2 #include <linux/interrupt.h> 3 #include <linux/device.h> 4 #include <linux/gfp.h> 5 6 /* 7 * Device resource management aware IRQ request/free implementation. 8 */ 9 struct irq_devres { 10 unsigned int irq; 11 void *dev_id; 12 }; 13 14 static void devm_irq_release(struct device *dev, void *res) 15 { 16 struct irq_devres *this = res; 17 18 free_irq(this->irq, this->dev_id); 19 } 20 21 static int devm_irq_match(struct device *dev, void *res, void *data) 22 { 23 struct irq_devres *this = res, *match = data; 24 25 return this->irq == match->irq && this->dev_id == match->dev_id; 26 } 27 28 /** 29 * devm_request_threaded_irq - allocate an interrupt line for a managed device 30 * @dev: device to request interrupt for 31 * @irq: Interrupt line to allocate 32 * @handler: Function to be called when the IRQ occurs 33 * @thread_fn: function to be called in a threaded interrupt context. NULL 34 * for devices which handle everything in @handler 35 * @irqflags: Interrupt type flags 36 * @devname: An ascii name for the claiming device 37 * @dev_id: A cookie passed back to the handler function 38 * 39 * Except for the extra @dev argument, this function takes the 40 * same arguments and performs the same function as 41 * request_irq(). IRQs requested with this function will be 42 * automatically freed on driver detach. 43 * 44 * If an IRQ allocated with this function needs to be freed 45 * separately, devm_free_irq() must be used. 46 */ 47 int devm_request_threaded_irq(struct device *dev, unsigned int irq, 48 irq_handler_t handler, irq_handler_t thread_fn, 49 unsigned long irqflags, const char *devname, 50 void *dev_id) 51 { 52 struct irq_devres *dr; 53 int rc; 54 55 dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres), 56 GFP_KERNEL); 57 if (!dr) 58 return -ENOMEM; 59 60 rc = request_threaded_irq(irq, handler, thread_fn, irqflags, devname, 61 dev_id); 62 if (rc) { 63 devres_free(dr); 64 return rc; 65 } 66 67 dr->irq = irq; 68 dr->dev_id = dev_id; 69 devres_add(dev, dr); 70 71 return 0; 72 } 73 EXPORT_SYMBOL(devm_request_threaded_irq); 74 75 /** 76 * devm_free_irq - free an interrupt 77 * @dev: device to free interrupt for 78 * @irq: Interrupt line to free 79 * @dev_id: Device identity to free 80 * 81 * Except for the extra @dev argument, this function takes the 82 * same arguments and performs the same function as free_irq(). 83 * This function instead of free_irq() should be used to manually 84 * free IRQs allocated with devm_request_irq(). 85 */ 86 void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id) 87 { 88 struct irq_devres match_data = { irq, dev_id }; 89 90 free_irq(irq, dev_id); 91 WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match, 92 &match_data)); 93 } 94 EXPORT_SYMBOL(devm_free_irq); 95