mpic_msi.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; version 2 of the
  7. * License.
  8. *
  9. */
  10. #include <linux/irq.h>
  11. #include <linux/bitmap.h>
  12. #include <linux/msi.h>
  13. #include <asm/mpic.h>
  14. #include <asm/prom.h>
  15. #include <asm/hw_irq.h>
  16. #include <asm/ppc-pci.h>
  17. #include <sysdev/mpic.h>
  18. static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
  19. {
  20. pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
  21. bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
  22. }
  23. void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
  24. {
  25. unsigned long flags;
  26. /* The mpic calls this even when there is no allocator setup */
  27. if (!mpic->hwirq_bitmap)
  28. return;
  29. spin_lock_irqsave(&mpic->bitmap_lock, flags);
  30. __mpic_msi_reserve_hwirq(mpic, hwirq);
  31. spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
  32. }
  33. irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
  34. {
  35. unsigned long flags;
  36. int offset, order = get_count_order(num);
  37. spin_lock_irqsave(&mpic->bitmap_lock, flags);
  38. /*
  39. * This is fast, but stricter than we need. We might want to add
  40. * a fallback routine which does a linear search with no alignment.
  41. */
  42. offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
  43. order);
  44. spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
  45. pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
  46. num, order, offset);
  47. return offset;
  48. }
  49. void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
  50. {
  51. unsigned long flags;
  52. int order = get_count_order(num);
  53. pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
  54. num, order, offset);
  55. spin_lock_irqsave(&mpic->bitmap_lock, flags);
  56. bitmap_release_region(mpic->hwirq_bitmap, offset, order);
  57. spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
  58. }
  59. #ifdef CONFIG_MPIC_U3_HT_IRQS
  60. static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
  61. {
  62. irq_hw_number_t hwirq;
  63. struct irq_host_ops *ops = mpic->irqhost->ops;
  64. struct device_node *np;
  65. int flags, index, i;
  66. struct of_irq oirq;
  67. pr_debug("mpic: found U3, guessing msi allocator setup\n");
  68. /* Reserve source numbers we know are reserved in the HW */
  69. for (i = 0; i < 8; i++)
  70. __mpic_msi_reserve_hwirq(mpic, i);
  71. for (i = 42; i < 46; i++)
  72. __mpic_msi_reserve_hwirq(mpic, i);
  73. for (i = 100; i < 105; i++)
  74. __mpic_msi_reserve_hwirq(mpic, i);
  75. np = NULL;
  76. while ((np = of_find_all_nodes(np))) {
  77. pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
  78. index = 0;
  79. while (of_irq_map_one(np, index++, &oirq) == 0) {
  80. ops->xlate(mpic->irqhost, NULL, oirq.specifier,
  81. oirq.size, &hwirq, &flags);
  82. __mpic_msi_reserve_hwirq(mpic, hwirq);
  83. }
  84. }
  85. return 0;
  86. }
  87. #else
  88. static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
  89. {
  90. return -1;
  91. }
  92. #endif
  93. static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
  94. {
  95. int i, len;
  96. const u32 *p;
  97. p = of_get_property(mpic->irqhost->of_node,
  98. "msi-available-ranges", &len);
  99. if (!p) {
  100. pr_debug("mpic: no msi-available-ranges property found on %s\n",
  101. mpic->irqhost->of_node->full_name);
  102. return -ENODEV;
  103. }
  104. if (len % 8 != 0) {
  105. printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
  106. "property on %s\n", mpic->irqhost->of_node->full_name);
  107. return -EINVAL;
  108. }
  109. bitmap_allocate_region(mpic->hwirq_bitmap, 0,
  110. get_count_order(mpic->irq_count));
  111. /* Format is: (<u32 start> <u32 count>)+ */
  112. len /= sizeof(u32);
  113. for (i = 0; i < len / 2; i++, p += 2)
  114. mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
  115. return 0;
  116. }
  117. int mpic_msi_init_allocator(struct mpic *mpic)
  118. {
  119. int rc, size;
  120. BUG_ON(mpic->hwirq_bitmap);
  121. spin_lock_init(&mpic->bitmap_lock);
  122. size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
  123. pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
  124. mpic->hwirq_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);
  125. if (!mpic->hwirq_bitmap) {
  126. pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
  127. return -ENOMEM;
  128. }
  129. memset(mpic->hwirq_bitmap, 0, size);
  130. rc = mpic_msi_reserve_dt_hwirqs(mpic);
  131. if (rc) {
  132. if (mpic->flags & MPIC_U3_HT_IRQS)
  133. rc = mpic_msi_reserve_u3_hwirqs(mpic);
  134. if (rc)
  135. goto out_free;
  136. }
  137. return 0;
  138. out_free:
  139. if (mem_init_done)
  140. kfree(mpic->hwirq_bitmap);
  141. mpic->hwirq_bitmap = NULL;
  142. return rc;
  143. }