dynamic.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Dynamic IRQ management
  3. *
  4. * Copyright (C) 2010 Paul Mundt
  5. *
  6. * Modelled after arch/x86/kernel/apic/io_apic.c
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. */
  12. #define pr_fmt(fmt) "intc: " fmt
  13. #include <linux/irq.h>
  14. #include <linux/bitmap.h>
  15. #include <linux/spinlock.h>
  16. #include "internals.h" /* only for activate_irq() damage.. */
  17. /*
  18. * The intc_irq_map provides a global map of bound IRQ vectors for a
  19. * given platform. Allocation of IRQs are either static through the CPU
  20. * vector map, or dynamic in the case of board mux vectors or MSI.
  21. *
  22. * As this is a central point for all IRQ controllers on the system,
  23. * each of the available sources are mapped out here. This combined with
  24. * sparseirq makes it quite trivial to keep the vector map tightly packed
  25. * when dynamically creating IRQs, as well as tying in to otherwise
  26. * unused irq_desc positions in the sparse array.
  27. */
  28. static DECLARE_BITMAP(intc_irq_map, NR_IRQS);
  29. static DEFINE_RAW_SPINLOCK(vector_lock);
  30. /*
  31. * Dynamic IRQ allocation and deallocation
  32. */
  33. unsigned int create_irq_nr(unsigned int irq_want, int node)
  34. {
  35. unsigned int irq = 0, new;
  36. unsigned long flags;
  37. struct irq_desc *desc;
  38. raw_spin_lock_irqsave(&vector_lock, flags);
  39. /*
  40. * First try the wanted IRQ
  41. */
  42. if (test_and_set_bit(irq_want, intc_irq_map) == 0) {
  43. new = irq_want;
  44. } else {
  45. /* .. then fall back to scanning. */
  46. new = find_first_zero_bit(intc_irq_map, nr_irqs);
  47. if (unlikely(new == nr_irqs))
  48. goto out_unlock;
  49. __set_bit(new, intc_irq_map);
  50. }
  51. desc = irq_to_desc_alloc_node(new, node);
  52. if (unlikely(!desc)) {
  53. pr_err("can't get irq_desc for %d\n", new);
  54. goto out_unlock;
  55. }
  56. desc = move_irq_desc(desc, node);
  57. irq = new;
  58. out_unlock:
  59. raw_spin_unlock_irqrestore(&vector_lock, flags);
  60. if (irq > 0) {
  61. dynamic_irq_init(irq);
  62. activate_irq(irq);
  63. }
  64. return irq;
  65. }
  66. int create_irq(void)
  67. {
  68. int nid = cpu_to_node(smp_processor_id());
  69. int irq;
  70. irq = create_irq_nr(NR_IRQS_LEGACY, nid);
  71. if (irq == 0)
  72. irq = -1;
  73. return irq;
  74. }
  75. void destroy_irq(unsigned int irq)
  76. {
  77. unsigned long flags;
  78. dynamic_irq_cleanup(irq);
  79. raw_spin_lock_irqsave(&vector_lock, flags);
  80. __clear_bit(irq, intc_irq_map);
  81. raw_spin_unlock_irqrestore(&vector_lock, flags);
  82. }
  83. int reserve_irq_vector(unsigned int irq)
  84. {
  85. unsigned long flags;
  86. int ret = 0;
  87. raw_spin_lock_irqsave(&vector_lock, flags);
  88. if (test_and_set_bit(irq, intc_irq_map))
  89. ret = -EBUSY;
  90. raw_spin_unlock_irqrestore(&vector_lock, flags);
  91. return ret;
  92. }
  93. void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs)
  94. {
  95. unsigned long flags;
  96. int i;
  97. raw_spin_lock_irqsave(&vector_lock, flags);
  98. for (i = 0; i < nr_vecs; i++)
  99. __set_bit(evt2irq(vectors[i].vect), intc_irq_map);
  100. raw_spin_unlock_irqrestore(&vector_lock, flags);
  101. }
  102. void reserve_irq_legacy(void)
  103. {
  104. unsigned long flags;
  105. int i, j;
  106. raw_spin_lock_irqsave(&vector_lock, flags);
  107. j = find_first_bit(intc_irq_map, nr_irqs);
  108. for (i = 0; i < j; i++)
  109. __set_bit(i, intc_irq_map);
  110. raw_spin_unlock_irqrestore(&vector_lock, flags);
  111. }