uio_pci_generic_sva.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * UIO PCI Express sva driver
  4. *
  5. * Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC)
  6. */
  7. #include <linux/device.h>
  8. #include <linux/module.h>
  9. #include <linux/pci.h>
  10. #include <linux/uio_driver.h>
  11. #include <linux/iommu.h>
  12. struct uio_pci_sva_dev {
  13. struct pci_dev *pdev;
  14. struct uio_info info;
  15. struct iommu_sva *sva_handle;
  16. int pasid;
  17. };
  18. static irqreturn_t irq_handler(int irq, struct uio_info *dev_info)
  19. {
  20. return IRQ_HANDLED;
  21. }
  22. static int uio_pci_sva_open(struct uio_info *info, struct inode *inode)
  23. {
  24. struct iommu_sva *handle;
  25. struct uio_pci_sva_dev *udev = info->priv;
  26. struct iommu_domain *domain;
  27. if (!udev || !udev->pdev)
  28. return -ENODEV;
  29. domain = iommu_get_domain_for_dev(&udev->pdev->dev);
  30. if (domain)
  31. iommu_detach_device(domain, &udev->pdev->dev);
  32. handle = iommu_sva_bind_device(&udev->pdev->dev, current->mm);
  33. if (IS_ERR(handle))
  34. return -EINVAL;
  35. udev->pasid = iommu_sva_get_pasid(handle);
  36. udev->sva_handle = handle;
  37. return 0;
  38. }
  39. static int uio_pci_sva_release(struct uio_info *info, struct inode *inode)
  40. {
  41. struct uio_pci_sva_dev *udev = info->priv;
  42. if (!udev || !udev->pdev)
  43. return -ENODEV;
  44. iommu_sva_unbind_device(udev->sva_handle);
  45. return 0;
  46. }
  47. static int probe(struct pci_dev *pdev, const struct pci_device_id *id)
  48. {
  49. struct uio_pci_sva_dev *udev;
  50. int ret, i, irq = 0;
  51. ret = pci_enable_device(pdev);
  52. if (ret) {
  53. dev_err(&pdev->dev, "pci_enable_device failed: %d\n", ret);
  54. return ret;
  55. }
  56. ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
  57. if (ret)
  58. goto out_disable;
  59. pci_set_master(pdev);
  60. ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX | PCI_IRQ_MSI);
  61. if (ret > 0) {
  62. irq = pci_irq_vector(pdev, 0);
  63. if (irq < 0) {
  64. dev_err(&pdev->dev, "Failed to get MSI vector\n");
  65. ret = irq;
  66. goto out_disable;
  67. }
  68. } else
  69. dev_warn(&pdev->dev,
  70. "No IRQ vectors available (%d), using polling\n", ret);
  71. udev = devm_kzalloc(&pdev->dev, sizeof(struct uio_pci_sva_dev),
  72. GFP_KERNEL);
  73. if (!udev) {
  74. ret = -ENOMEM;
  75. goto out_disable;
  76. }
  77. udev->pdev = pdev;
  78. udev->info.name = "uio_pci_sva";
  79. udev->info.version = "0.0.1";
  80. udev->info.open = uio_pci_sva_open;
  81. udev->info.release = uio_pci_sva_release;
  82. udev->info.irq = irq;
  83. udev->info.handler = irq_handler;
  84. udev->info.priv = udev;
  85. for (i = 0; i < MAX_UIO_MAPS; i++) {
  86. struct resource *r = &pdev->resource[i];
  87. struct uio_mem *uiomem = &udev->info.mem[i];
  88. if (r->flags != (IORESOURCE_SIZEALIGN | IORESOURCE_MEM))
  89. continue;
  90. if (uiomem >= &udev->info.mem[MAX_UIO_MAPS]) {
  91. dev_warn(&pdev->dev, "Do not support more than %d iomem\n",
  92. MAX_UIO_MAPS);
  93. break;
  94. }
  95. uiomem->memtype = UIO_MEM_PHYS;
  96. uiomem->addr = r->start & PAGE_MASK;
  97. uiomem->offs = r->start & ~PAGE_MASK;
  98. uiomem->size =
  99. (uiomem->offs + resource_size(r) + PAGE_SIZE - 1) &
  100. PAGE_MASK;
  101. uiomem->name = r->name;
  102. }
  103. ret = devm_uio_register_device(&pdev->dev, &udev->info);
  104. if (ret) {
  105. dev_err(&pdev->dev, "Failed to register uio device\n");
  106. goto out_free;
  107. }
  108. pci_set_drvdata(pdev, udev);
  109. return 0;
  110. out_free:
  111. kfree(udev);
  112. out_disable:
  113. pci_disable_device(pdev);
  114. return ret;
  115. }
  116. static void remove(struct pci_dev *pdev)
  117. {
  118. struct uio_pci_sva_dev *udev = pci_get_drvdata(pdev);
  119. pci_release_regions(pdev);
  120. pci_disable_device(pdev);
  121. kfree(udev);
  122. }
  123. static ssize_t pasid_show(struct device *dev,
  124. struct device_attribute *attr, char *buf)
  125. {
  126. struct pci_dev *pdev = to_pci_dev(dev);
  127. struct uio_pci_sva_dev *udev = pci_get_drvdata(pdev);
  128. return sysfs_emit(buf, "%d\n", udev->pasid);
  129. }
  130. static DEVICE_ATTR_RO(pasid);
  131. static struct attribute *uio_pci_sva_attrs[] = {
  132. &dev_attr_pasid.attr,
  133. NULL
  134. };
  135. static const struct attribute_group uio_pci_sva_attr_group = {
  136. .attrs = uio_pci_sva_attrs,
  137. };
  138. static const struct attribute_group *uio_pci_sva_attr_groups[] = {
  139. &uio_pci_sva_attr_group,
  140. NULL
  141. };
  142. static struct pci_driver uio_pci_generic_sva_driver = {
  143. .name = "uio_pci_sva",
  144. .dev_groups = uio_pci_sva_attr_groups,
  145. .id_table = NULL,
  146. .probe = probe,
  147. .remove = remove,
  148. };
  149. module_pci_driver(uio_pci_generic_sva_driver);
  150. MODULE_VERSION("0.0.01");
  151. MODULE_LICENSE("GPL v2");
  152. MODULE_AUTHOR("Yaxing Guo <guoyaxing@bosc.ac.cn>");
  153. MODULE_DESCRIPTION("Generic UIO sva driver for PCI");