#include <linux/module.h>1#include <linux/interrupt.h>2#include <linux/device.h>3#include <linux/gfp.h>45/*6* Device resource management aware IRQ request/free implementation.7*/8struct irq_devres {9unsigned int irq;10void *dev_id;11};1213static void devm_irq_release(struct device *dev, void *res)14{15struct irq_devres *this = res;1617free_irq(this->irq, this->dev_id);18}1920static int devm_irq_match(struct device *dev, void *res, void *data)21{22struct irq_devres *this = res, *match = data;2324return this->irq == match->irq && this->dev_id == match->dev_id;25}2627/**28* devm_request_threaded_irq - allocate an interrupt line for a managed device29* @dev: device to request interrupt for30* @irq: Interrupt line to allocate31* @handler: Function to be called when the IRQ occurs32* @thread_fn: function to be called in a threaded interrupt context. NULL33* for devices which handle everything in @handler34* @irqflags: Interrupt type flags35* @devname: An ascii name for the claiming device36* @dev_id: A cookie passed back to the handler function37*38* Except for the extra @dev argument, this function takes the39* same arguments and performs the same function as40* request_irq(). IRQs requested with this function will be41* automatically freed on driver detach.42*43* If an IRQ allocated with this function needs to be freed44* separately, devm_free_irq() must be used.45*/46int devm_request_threaded_irq(struct device *dev, unsigned int irq,47irq_handler_t handler, irq_handler_t thread_fn,48unsigned long irqflags, const char *devname,49void *dev_id)50{51struct irq_devres *dr;52int rc;5354dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),55GFP_KERNEL);56if (!dr)57return -ENOMEM;5859rc = request_threaded_irq(irq, handler, thread_fn, irqflags, devname,60dev_id);61if (rc) {62devres_free(dr);63return rc;64}6566dr->irq = irq;67dr->dev_id = dev_id;68devres_add(dev, dr);6970return 0;71}72EXPORT_SYMBOL(devm_request_threaded_irq);7374/**75* devm_free_irq - free an interrupt76* @dev: device to free interrupt for77* @irq: Interrupt line to free78* @dev_id: Device identity to free79*80* Except for the extra @dev argument, this function takes the81* same arguments and performs the same function as free_irq().82* This function instead of free_irq() should be used to manually83* free IRQs allocated with devm_request_irq().84*/85void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)86{87struct irq_devres match_data = { irq, dev_id };8889free_irq(irq, dev_id);90WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,91&match_data));92}93EXPORT_SYMBOL(devm_free_irq);949596