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