pci-cxl.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright 2014-2016 IBM Corp.
  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; either version
  7. * 2 of the License, or (at your option) any later version.
  8. */
  9. #include <linux/module.h>
  10. #include <asm/pnv-pci.h>
  11. #include <asm/opal.h>
  12. #include "pci.h"
  13. int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode)
  14. {
  15. struct pci_controller *hose = pci_bus_to_host(dev->bus);
  16. struct pnv_phb *phb = hose->private_data;
  17. struct pnv_ioda_pe *pe;
  18. int rc;
  19. pe = pnv_ioda_get_pe(dev);
  20. if (!pe)
  21. return -ENODEV;
  22. pe_info(pe, "Switching PHB to CXL\n");
  23. rc = opal_pci_set_phb_cxl_mode(phb->opal_id, mode, pe->pe_number);
  24. if (rc == OPAL_UNSUPPORTED)
  25. dev_err(&dev->dev, "Required cxl mode not supported by firmware - update skiboot\n");
  26. else if (rc)
  27. dev_err(&dev->dev, "opal_pci_set_phb_cxl_mode failed: %i\n", rc);
  28. return rc;
  29. }
  30. EXPORT_SYMBOL(pnv_phb_to_cxl_mode);
  31. /* Find PHB for cxl dev and allocate MSI hwirqs?
  32. * Returns the absolute hardware IRQ number
  33. */
  34. int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num)
  35. {
  36. struct pci_controller *hose = pci_bus_to_host(dev->bus);
  37. struct pnv_phb *phb = hose->private_data;
  38. int hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, num);
  39. if (hwirq < 0) {
  40. dev_warn(&dev->dev, "Failed to find a free MSI\n");
  41. return -ENOSPC;
  42. }
  43. return phb->msi_base + hwirq;
  44. }
  45. EXPORT_SYMBOL(pnv_cxl_alloc_hwirqs);
  46. void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num)
  47. {
  48. struct pci_controller *hose = pci_bus_to_host(dev->bus);
  49. struct pnv_phb *phb = hose->private_data;
  50. msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, num);
  51. }
  52. EXPORT_SYMBOL(pnv_cxl_release_hwirqs);
  53. void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs,
  54. struct pci_dev *dev)
  55. {
  56. struct pci_controller *hose = pci_bus_to_host(dev->bus);
  57. struct pnv_phb *phb = hose->private_data;
  58. int i, hwirq;
  59. for (i = 1; i < CXL_IRQ_RANGES; i++) {
  60. if (!irqs->range[i])
  61. continue;
  62. pr_devel("cxl release irq range 0x%x: offset: 0x%lx limit: %ld\n",
  63. i, irqs->offset[i],
  64. irqs->range[i]);
  65. hwirq = irqs->offset[i] - phb->msi_base;
  66. msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq,
  67. irqs->range[i]);
  68. }
  69. }
  70. EXPORT_SYMBOL(pnv_cxl_release_hwirq_ranges);
  71. int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs,
  72. struct pci_dev *dev, int num)
  73. {
  74. struct pci_controller *hose = pci_bus_to_host(dev->bus);
  75. struct pnv_phb *phb = hose->private_data;
  76. int i, hwirq, try;
  77. memset(irqs, 0, sizeof(struct cxl_irq_ranges));
  78. /* 0 is reserved for the multiplexed PSL DSI interrupt */
  79. for (i = 1; i < CXL_IRQ_RANGES && num; i++) {
  80. try = num;
  81. while (try) {
  82. hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, try);
  83. if (hwirq >= 0)
  84. break;
  85. try /= 2;
  86. }
  87. if (!try)
  88. goto fail;
  89. irqs->offset[i] = phb->msi_base + hwirq;
  90. irqs->range[i] = try;
  91. pr_devel("cxl alloc irq range 0x%x: offset: 0x%lx limit: %li\n",
  92. i, irqs->offset[i], irqs->range[i]);
  93. num -= try;
  94. }
  95. if (num)
  96. goto fail;
  97. return 0;
  98. fail:
  99. pnv_cxl_release_hwirq_ranges(irqs, dev);
  100. return -ENOSPC;
  101. }
  102. EXPORT_SYMBOL(pnv_cxl_alloc_hwirq_ranges);
  103. int pnv_cxl_get_irq_count(struct pci_dev *dev)
  104. {
  105. struct pci_controller *hose = pci_bus_to_host(dev->bus);
  106. struct pnv_phb *phb = hose->private_data;
  107. return phb->msi_bmp.irq_count;
  108. }
  109. EXPORT_SYMBOL(pnv_cxl_get_irq_count);
  110. int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq,
  111. unsigned int virq)
  112. {
  113. struct pci_controller *hose = pci_bus_to_host(dev->bus);
  114. struct pnv_phb *phb = hose->private_data;
  115. unsigned int xive_num = hwirq - phb->msi_base;
  116. struct pnv_ioda_pe *pe;
  117. int rc;
  118. if (!(pe = pnv_ioda_get_pe(dev)))
  119. return -ENODEV;
  120. /* Assign XIVE to PE */
  121. rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num);
  122. if (rc) {
  123. pe_warn(pe, "%s: OPAL error %d setting msi_base 0x%x "
  124. "hwirq 0x%x XIVE 0x%x PE\n",
  125. pci_name(dev), rc, phb->msi_base, hwirq, xive_num);
  126. return -EIO;
  127. }
  128. pnv_set_msi_irq_chip(phb, virq);
  129. return 0;
  130. }
  131. EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup);
  132. #if IS_MODULE(CONFIG_CXL)
  133. static inline int get_cxl_module(void)
  134. {
  135. struct module *cxl_module;
  136. mutex_lock(&module_mutex);
  137. cxl_module = find_module("cxl");
  138. if (cxl_module)
  139. __module_get(cxl_module);
  140. mutex_unlock(&module_mutex);
  141. if (!cxl_module)
  142. return -ENODEV;
  143. return 0;
  144. }
  145. #else
  146. static inline int get_cxl_module(void) { return 0; }
  147. #endif