ats.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * drivers/pci/ats.c
  3. *
  4. * Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@intel.com>
  5. *
  6. * PCI Express I/O Virtualization (IOV) support.
  7. * Address Translation Service 1.0
  8. */
  9. #include <linux/pci-ats.h>
  10. #include <linux/pci.h>
  11. #include "pci.h"
  12. static int ats_alloc_one(struct pci_dev *dev, int ps)
  13. {
  14. int pos;
  15. u16 cap;
  16. struct pci_ats *ats;
  17. pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
  18. if (!pos)
  19. return -ENODEV;
  20. ats = kzalloc(sizeof(*ats), GFP_KERNEL);
  21. if (!ats)
  22. return -ENOMEM;
  23. ats->pos = pos;
  24. ats->stu = ps;
  25. pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
  26. ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
  27. PCI_ATS_MAX_QDEP;
  28. dev->ats = ats;
  29. return 0;
  30. }
  31. static void ats_free_one(struct pci_dev *dev)
  32. {
  33. kfree(dev->ats);
  34. dev->ats = NULL;
  35. }
  36. /**
  37. * pci_enable_ats - enable the ATS capability
  38. * @dev: the PCI device
  39. * @ps: the IOMMU page shift
  40. *
  41. * Returns 0 on success, or negative on failure.
  42. */
  43. int pci_enable_ats(struct pci_dev *dev, int ps)
  44. {
  45. int rc;
  46. u16 ctrl;
  47. BUG_ON(dev->ats && dev->ats->is_enabled);
  48. if (ps < PCI_ATS_MIN_STU)
  49. return -EINVAL;
  50. if (dev->is_physfn || dev->is_virtfn) {
  51. struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
  52. mutex_lock(&pdev->sriov->lock);
  53. if (pdev->ats)
  54. rc = pdev->ats->stu == ps ? 0 : -EINVAL;
  55. else
  56. rc = ats_alloc_one(pdev, ps);
  57. if (!rc)
  58. pdev->ats->ref_cnt++;
  59. mutex_unlock(&pdev->sriov->lock);
  60. if (rc)
  61. return rc;
  62. }
  63. if (!dev->is_physfn) {
  64. rc = ats_alloc_one(dev, ps);
  65. if (rc)
  66. return rc;
  67. }
  68. ctrl = PCI_ATS_CTRL_ENABLE;
  69. if (!dev->is_virtfn)
  70. ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
  71. pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
  72. dev->ats->is_enabled = 1;
  73. return 0;
  74. }
  75. EXPORT_SYMBOL_GPL(pci_enable_ats);
  76. /**
  77. * pci_disable_ats - disable the ATS capability
  78. * @dev: the PCI device
  79. */
  80. void pci_disable_ats(struct pci_dev *dev)
  81. {
  82. u16 ctrl;
  83. BUG_ON(!dev->ats || !dev->ats->is_enabled);
  84. pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
  85. ctrl &= ~PCI_ATS_CTRL_ENABLE;
  86. pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
  87. dev->ats->is_enabled = 0;
  88. if (dev->is_physfn || dev->is_virtfn) {
  89. struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
  90. mutex_lock(&pdev->sriov->lock);
  91. pdev->ats->ref_cnt--;
  92. if (!pdev->ats->ref_cnt)
  93. ats_free_one(pdev);
  94. mutex_unlock(&pdev->sriov->lock);
  95. }
  96. if (!dev->is_physfn)
  97. ats_free_one(dev);
  98. }
  99. EXPORT_SYMBOL_GPL(pci_disable_ats);
  100. /**
  101. * pci_ats_queue_depth - query the ATS Invalidate Queue Depth
  102. * @dev: the PCI device
  103. *
  104. * Returns the queue depth on success, or negative on failure.
  105. *
  106. * The ATS spec uses 0 in the Invalidate Queue Depth field to
  107. * indicate that the function can accept 32 Invalidate Request.
  108. * But here we use the `real' values (i.e. 1~32) for the Queue
  109. * Depth; and 0 indicates the function shares the Queue with
  110. * other functions (doesn't exclusively own a Queue).
  111. */
  112. int pci_ats_queue_depth(struct pci_dev *dev)
  113. {
  114. int pos;
  115. u16 cap;
  116. if (dev->is_virtfn)
  117. return 0;
  118. if (dev->ats)
  119. return dev->ats->qdep;
  120. pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
  121. if (!pos)
  122. return -ENODEV;
  123. pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
  124. return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
  125. PCI_ATS_MAX_QDEP;
  126. }
  127. EXPORT_SYMBOL_GPL(pci_ats_queue_depth);