devres.c 2.4 KB

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