devres.c 2.3 KB

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