devres.c 2.3 KB

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