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