msi_ia64.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * MSI hooks for standard x86 apic
  3. */
  4. #include <linux/pci.h>
  5. #include <linux/irq.h>
  6. #include <linux/msi.h>
  7. #include <linux/dmar.h>
  8. #include <asm/smp.h>
  9. #include <asm/msidef.h>
  10. static struct irq_chip ia64_msi_chip;
  11. #ifdef CONFIG_SMP
  12. static int ia64_set_msi_irq_affinity(unsigned int irq,
  13. const cpumask_t *cpu_mask)
  14. {
  15. struct msi_msg msg;
  16. u32 addr, data;
  17. int cpu = first_cpu(*cpu_mask);
  18. if (!cpu_online(cpu))
  19. return -1;
  20. if (irq_prepare_move(irq, cpu))
  21. return -1;
  22. read_msi_msg(irq, &msg);
  23. addr = msg.address_lo;
  24. addr &= MSI_ADDR_DEST_ID_MASK;
  25. addr |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
  26. msg.address_lo = addr;
  27. data = msg.data;
  28. data &= MSI_DATA_VECTOR_MASK;
  29. data |= MSI_DATA_VECTOR(irq_to_vector(irq));
  30. msg.data = data;
  31. write_msi_msg(irq, &msg);
  32. cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
  33. return 0;
  34. }
  35. #endif /* CONFIG_SMP */
  36. int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
  37. {
  38. struct msi_msg msg;
  39. unsigned long dest_phys_id;
  40. int irq, vector;
  41. cpumask_t mask;
  42. irq = create_irq();
  43. if (irq < 0)
  44. return irq;
  45. set_irq_msi(irq, desc);
  46. cpus_and(mask, irq_to_domain(irq), cpu_online_map);
  47. dest_phys_id = cpu_physical_id(first_cpu(mask));
  48. vector = irq_to_vector(irq);
  49. msg.address_hi = 0;
  50. msg.address_lo =
  51. MSI_ADDR_HEADER |
  52. MSI_ADDR_DEST_MODE_PHYS |
  53. MSI_ADDR_REDIRECTION_CPU |
  54. MSI_ADDR_DEST_ID_CPU(dest_phys_id);
  55. msg.data =
  56. MSI_DATA_TRIGGER_EDGE |
  57. MSI_DATA_LEVEL_ASSERT |
  58. MSI_DATA_DELIVERY_FIXED |
  59. MSI_DATA_VECTOR(vector);
  60. write_msi_msg(irq, &msg);
  61. set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
  62. return 0;
  63. }
  64. void ia64_teardown_msi_irq(unsigned int irq)
  65. {
  66. destroy_irq(irq);
  67. }
  68. static void ia64_ack_msi_irq(unsigned int irq)
  69. {
  70. irq_complete_move(irq);
  71. move_native_irq(irq);
  72. ia64_eoi();
  73. }
  74. static int ia64_msi_retrigger_irq(unsigned int irq)
  75. {
  76. unsigned int vector = irq_to_vector(irq);
  77. ia64_resend_irq(vector);
  78. return 1;
  79. }
  80. /*
  81. * Generic ops used on most IA64 platforms.
  82. */
  83. static struct irq_chip ia64_msi_chip = {
  84. .name = "PCI-MSI",
  85. .mask = mask_msi_irq,
  86. .unmask = unmask_msi_irq,
  87. .ack = ia64_ack_msi_irq,
  88. #ifdef CONFIG_SMP
  89. .set_affinity = ia64_set_msi_irq_affinity,
  90. #endif
  91. .retrigger = ia64_msi_retrigger_irq,
  92. };
  93. int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
  94. {
  95. if (platform_setup_msi_irq)
  96. return platform_setup_msi_irq(pdev, desc);
  97. return ia64_setup_msi_irq(pdev, desc);
  98. }
  99. void arch_teardown_msi_irq(unsigned int irq)
  100. {
  101. if (platform_teardown_msi_irq)
  102. return platform_teardown_msi_irq(irq);
  103. return ia64_teardown_msi_irq(irq);
  104. }
  105. #ifdef CONFIG_DMAR
  106. #ifdef CONFIG_SMP
  107. static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
  108. {
  109. struct irq_cfg *cfg = irq_cfg + irq;
  110. struct msi_msg msg;
  111. int cpu = cpumask_first(mask);
  112. if (!cpu_online(cpu))
  113. return -1;
  114. if (irq_prepare_move(irq, cpu))
  115. return -1;
  116. dmar_msi_read(irq, &msg);
  117. msg.data &= ~MSI_DATA_VECTOR_MASK;
  118. msg.data |= MSI_DATA_VECTOR(cfg->vector);
  119. msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
  120. msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
  121. dmar_msi_write(irq, &msg);
  122. cpumask_copy(irq_desc[irq].affinity, mask);
  123. return 0;
  124. }
  125. #endif /* CONFIG_SMP */
  126. static struct irq_chip dmar_msi_type = {
  127. .name = "DMAR_MSI",
  128. .unmask = dmar_msi_unmask,
  129. .mask = dmar_msi_mask,
  130. .ack = ia64_ack_msi_irq,
  131. #ifdef CONFIG_SMP
  132. .set_affinity = dmar_msi_set_affinity,
  133. #endif
  134. .retrigger = ia64_msi_retrigger_irq,
  135. };
  136. static int
  137. msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
  138. {
  139. struct irq_cfg *cfg = irq_cfg + irq;
  140. unsigned dest;
  141. cpumask_t mask;
  142. cpus_and(mask, irq_to_domain(irq), cpu_online_map);
  143. dest = cpu_physical_id(first_cpu(mask));
  144. msg->address_hi = 0;
  145. msg->address_lo =
  146. MSI_ADDR_HEADER |
  147. MSI_ADDR_DEST_MODE_PHYS |
  148. MSI_ADDR_REDIRECTION_CPU |
  149. MSI_ADDR_DEST_ID_CPU(dest);
  150. msg->data =
  151. MSI_DATA_TRIGGER_EDGE |
  152. MSI_DATA_LEVEL_ASSERT |
  153. MSI_DATA_DELIVERY_FIXED |
  154. MSI_DATA_VECTOR(cfg->vector);
  155. return 0;
  156. }
  157. int arch_setup_dmar_msi(unsigned int irq)
  158. {
  159. int ret;
  160. struct msi_msg msg;
  161. ret = msi_compose_msg(NULL, irq, &msg);
  162. if (ret < 0)
  163. return ret;
  164. dmar_msi_write(irq, &msg);
  165. set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
  166. "edge");
  167. return 0;
  168. }
  169. #endif /* CONFIG_DMAR */