irq-gic-v3-its-msi-parent.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. // Copyright (C) 2013-2015 ARM Limited, All Rights Reserved.
  3. // Author: Marc Zyngier <marc.zyngier@arm.com>
  4. // Copyright (C) 2022 Linutronix GmbH
  5. // Copyright (C) 2022 Intel
  6. #include <linux/acpi_iort.h>
  7. #include <linux/pci.h>
  8. #include "irq-gic-common.h"
  9. #include "irq-msi-lib.h"
  10. #define ITS_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
  11. MSI_FLAG_USE_DEF_CHIP_OPS | \
  12. MSI_FLAG_PCI_MSI_MASK_PARENT)
  13. #define ITS_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \
  14. MSI_FLAG_PCI_MSIX | \
  15. MSI_FLAG_MULTI_PCI_MSI)
  16. #ifdef CONFIG_PCI_MSI
  17. static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data)
  18. {
  19. int msi, msix, *count = data;
  20. msi = max(pci_msi_vec_count(pdev), 0);
  21. msix = max(pci_msix_vec_count(pdev), 0);
  22. *count += max(msi, msix);
  23. return 0;
  24. }
  25. static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
  26. {
  27. struct pci_dev **alias_dev = data;
  28. *alias_dev = pdev;
  29. return 0;
  30. }
  31. static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
  32. int nvec, msi_alloc_info_t *info)
  33. {
  34. struct pci_dev *pdev, *alias_dev;
  35. struct msi_domain_info *msi_info;
  36. int alias_count = 0, minnvec = 1;
  37. if (!dev_is_pci(dev))
  38. return -EINVAL;
  39. pdev = to_pci_dev(dev);
  40. /*
  41. * If pdev is downstream of any aliasing bridges, take an upper
  42. * bound of how many other vectors could map to the same DevID.
  43. * Also tell the ITS that the signalling will come from a proxy
  44. * device, and that special allocation rules apply.
  45. */
  46. pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev);
  47. if (alias_dev != pdev) {
  48. if (alias_dev->subordinate)
  49. pci_walk_bus(alias_dev->subordinate,
  50. its_pci_msi_vec_count, &alias_count);
  51. info->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE;
  52. }
  53. /* ITS specific DeviceID, as the core ITS ignores dev. */
  54. info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain->parent, pdev);
  55. /*
  56. * @domain->msi_domain_info->hwsize contains the size of the
  57. * MSI[-X] domain, but vector allocation happens one by one. This
  58. * needs some thought when MSI comes into play as the size of MSI
  59. * might be unknown at domain creation time and therefore set to
  60. * MSI_MAX_INDEX.
  61. */
  62. msi_info = msi_get_domain_info(domain);
  63. if (msi_info->hwsize > nvec)
  64. nvec = msi_info->hwsize;
  65. /*
  66. * Always allocate a power of 2, and special case device 0 for
  67. * broken systems where the DevID is not wired (and all devices
  68. * appear as DevID 0). For that reason, we generously allocate a
  69. * minimum of 32 MSIs for DevID 0. If you want more because all
  70. * your devices are aliasing to DevID 0, consider fixing your HW.
  71. */
  72. nvec = max(nvec, alias_count);
  73. if (!info->scratchpad[0].ul)
  74. minnvec = 32;
  75. nvec = max_t(int, minnvec, roundup_pow_of_two(nvec));
  76. msi_info = msi_get_domain_info(domain->parent);
  77. return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info);
  78. }
  79. #else /* CONFIG_PCI_MSI */
  80. #define its_pci_msi_prepare NULL
  81. #endif /* !CONFIG_PCI_MSI */
  82. static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev,
  83. u32 *dev_id)
  84. {
  85. int ret, index = 0;
  86. /* Suck the DeviceID out of the msi-parent property */
  87. do {
  88. struct of_phandle_args args;
  89. ret = of_parse_phandle_with_args(dev->of_node,
  90. "msi-parent", "#msi-cells",
  91. index, &args);
  92. if (args.np == irq_domain_get_of_node(domain)) {
  93. if (WARN_ON(args.args_count != 1))
  94. return -EINVAL;
  95. *dev_id = args.args[0];
  96. break;
  97. }
  98. index++;
  99. } while (!ret);
  100. return ret;
  101. }
  102. int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
  103. {
  104. return -1;
  105. }
  106. static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
  107. int nvec, msi_alloc_info_t *info)
  108. {
  109. struct msi_domain_info *msi_info;
  110. u32 dev_id;
  111. int ret;
  112. if (dev->of_node)
  113. ret = of_pmsi_get_dev_id(domain->parent, dev, &dev_id);
  114. else
  115. ret = iort_pmsi_get_dev_id(dev, &dev_id);
  116. if (ret)
  117. return ret;
  118. /* ITS specific DeviceID, as the core ITS ignores dev. */
  119. info->scratchpad[0].ul = dev_id;
  120. /*
  121. * @domain->msi_domain_info->hwsize contains the size of the device
  122. * domain, but vector allocation happens one by one.
  123. */
  124. msi_info = msi_get_domain_info(domain);
  125. if (msi_info->hwsize > nvec)
  126. nvec = msi_info->hwsize;
  127. /* Allocate at least 32 MSIs, and always as a power of 2 */
  128. nvec = max_t(int, 32, roundup_pow_of_two(nvec));
  129. msi_info = msi_get_domain_info(domain->parent);
  130. return msi_info->ops->msi_prepare(domain->parent,
  131. dev, nvec, info);
  132. }
  133. static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
  134. struct irq_domain *real_parent, struct msi_domain_info *info)
  135. {
  136. if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
  137. return false;
  138. switch(info->bus_token) {
  139. case DOMAIN_BUS_PCI_DEVICE_MSI:
  140. case DOMAIN_BUS_PCI_DEVICE_MSIX:
  141. /*
  142. * FIXME: This probably should be done after a (not yet
  143. * existing) post domain creation callback once to make
  144. * support for dynamic post-enable MSI-X allocations
  145. * work without having to reevaluate the domain size
  146. * over and over. It is known already at allocation
  147. * time via info->hwsize.
  148. *
  149. * That should work perfectly fine for MSI/MSI-X but needs
  150. * some thoughts for purely software managed MSI domains
  151. * where the index space is only limited artificially via
  152. * %MSI_MAX_INDEX.
  153. */
  154. info->ops->msi_prepare = its_pci_msi_prepare;
  155. break;
  156. case DOMAIN_BUS_DEVICE_MSI:
  157. case DOMAIN_BUS_WIRED_TO_MSI:
  158. /*
  159. * FIXME: See the above PCI prepare comment. The domain
  160. * size is also known at domain creation time.
  161. */
  162. info->ops->msi_prepare = its_pmsi_prepare;
  163. break;
  164. default:
  165. /* Confused. How did the lib return true? */
  166. WARN_ON_ONCE(1);
  167. return false;
  168. }
  169. return true;
  170. }
  171. const struct msi_parent_ops gic_v3_its_msi_parent_ops = {
  172. .supported_flags = ITS_MSI_FLAGS_SUPPORTED,
  173. .required_flags = ITS_MSI_FLAGS_REQUIRED,
  174. .bus_select_token = DOMAIN_BUS_NEXUS,
  175. .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
  176. .prefix = "ITS-",
  177. .init_dev_msi_info = its_init_dev_msi_info,
  178. };