0002-n1sdp-pci_quirk-add-acs-override-for-PCI-devices.patch 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. From fc8605e74b51d9e0ab8efd0489eca2e11d807f07 Mon Sep 17 00:00:00 2001
  2. From: Manoj Kumar <manoj.kumar3@arm.com>
  3. Date: Tue, 31 Aug 2021 16:15:38 +0000
  4. Subject: [PATCH] n1sdp: pci_quirk: add acs override for PCI devices
  5. Patch taken from:
  6. https://gitlab.com/Queuecumber/linux-acs-override/raw/master/workspaces/5.4/acso.patch
  7. Change-Id: Ib926bf50524ce9990fbaa2f2f8670fe84bd571f9
  8. Signed-off-by: Manoj Kumar <manoj.kumar3@arm.com>
  9. Upstream-Status: Inappropriate [will not be submitted as its a workaround to address hardware issue]
  10. Signed-off-by: Khasim Syed Mohammed <khasim.mohammed@arm.com>
  11. Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
  12. Signed-off-by: Adam Johnston <adam.johnston@arm.com>
  13. ---
  14. .../admin-guide/kernel-parameters.txt | 8 ++
  15. drivers/pci/quirks.c | 102 ++++++++++++++++++
  16. 2 files changed, 110 insertions(+)
  17. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
  18. index 963cdaecabcb..8e94af513b9f 100644
  19. --- a/Documentation/admin-guide/kernel-parameters.txt
  20. +++ b/Documentation/admin-guide/kernel-parameters.txt
  21. @@ -4162,6 +4162,14 @@
  22. nomsi [MSI] If the PCI_MSI kernel config parameter is
  23. enabled, this kernel boot option can be used to
  24. disable the use of MSI interrupts system-wide.
  25. + pcie_acs_override [PCIE] Override missing PCIe ACS support for
  26. + downstream
  27. + All downstream ports - full ACS capabilities
  28. + multfunction
  29. + All multifunction devices - multifunction ACS subset
  30. + id:nnnn:nnnn
  31. + Specfic device - full ACS capabilities
  32. + Specified as vid:did (vendor/device ID) in hex
  33. noioapicquirk [APIC] Disable all boot interrupt quirks.
  34. Safety option to keep boot IRQs enabled. This
  35. should never be necessary.
  36. diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
  37. index 285acc4aaccc..d6ebef1f30db 100644
  38. --- a/drivers/pci/quirks.c
  39. +++ b/drivers/pci/quirks.c
  40. @@ -3612,6 +3612,107 @@ static void quirk_no_bus_reset(struct pci_dev *dev)
  41. dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET;
  42. }
  43. +static bool acs_on_downstream;
  44. +static bool acs_on_multifunction;
  45. +
  46. +#define NUM_ACS_IDS 16
  47. +struct acs_on_id {
  48. + unsigned short vendor;
  49. + unsigned short device;
  50. +};
  51. +static struct acs_on_id acs_on_ids[NUM_ACS_IDS];
  52. +static u8 max_acs_id;
  53. +
  54. +static __init int pcie_acs_override_setup(char *p)
  55. +{
  56. + if (!p)
  57. + return -EINVAL;
  58. +
  59. + while (*p) {
  60. + if (!strncmp(p, "downstream", 10))
  61. + acs_on_downstream = true;
  62. + if (!strncmp(p, "multifunction", 13))
  63. + acs_on_multifunction = true;
  64. + if (!strncmp(p, "id:", 3)) {
  65. + char opt[5];
  66. + int ret;
  67. + long val;
  68. +
  69. + if (max_acs_id >= NUM_ACS_IDS - 1) {
  70. + pr_warn("Out of PCIe ACS override slots (%d)\n",
  71. + NUM_ACS_IDS);
  72. + goto next;
  73. + }
  74. +
  75. + p += 3;
  76. + snprintf(opt, 5, "%s", p);
  77. + ret = kstrtol(opt, 16, &val);
  78. + if (ret) {
  79. + pr_warn("PCIe ACS ID parse error %d\n", ret);
  80. + goto next;
  81. + }
  82. + acs_on_ids[max_acs_id].vendor = val;
  83. +
  84. + p += strcspn(p, ":");
  85. + if (*p != ':') {
  86. + pr_warn("PCIe ACS invalid ID\n");
  87. + goto next;
  88. + }
  89. +
  90. + p++;
  91. + snprintf(opt, 5, "%s", p);
  92. + ret = kstrtol(opt, 16, &val);
  93. + if (ret) {
  94. + pr_warn("PCIe ACS ID parse error %d\n", ret);
  95. + goto next;
  96. + }
  97. + acs_on_ids[max_acs_id].device = val;
  98. + max_acs_id++;
  99. + }
  100. +next:
  101. + p += strcspn(p, ",");
  102. + if (*p == ',')
  103. + p++;
  104. + }
  105. +
  106. + if (acs_on_downstream || acs_on_multifunction || max_acs_id)
  107. + pr_warn("Warning: PCIe ACS overrides enabled; This may allow non-IOMMU protected peer-to-peer DMA\n");
  108. +
  109. + return 0;
  110. +}
  111. +early_param("pcie_acs_override", pcie_acs_override_setup);
  112. +
  113. +static int pcie_acs_overrides(struct pci_dev *dev, u16 acs_flags)
  114. +{
  115. + int i;
  116. +
  117. + /* Never override ACS for legacy devices or devices with ACS caps */
  118. + if (!pci_is_pcie(dev) ||
  119. + pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS))
  120. + return -ENOTTY;
  121. +
  122. + for (i = 0; i < max_acs_id; i++)
  123. + if (acs_on_ids[i].vendor == dev->vendor &&
  124. + acs_on_ids[i].device == dev->device)
  125. + return 1;
  126. +
  127. + switch (pci_pcie_type(dev)) {
  128. + case PCI_EXP_TYPE_DOWNSTREAM:
  129. + case PCI_EXP_TYPE_ROOT_PORT:
  130. + if (acs_on_downstream)
  131. + return 1;
  132. + break;
  133. + case PCI_EXP_TYPE_ENDPOINT:
  134. + case PCI_EXP_TYPE_UPSTREAM:
  135. + case PCI_EXP_TYPE_LEG_END:
  136. + case PCI_EXP_TYPE_RC_END:
  137. + if (acs_on_multifunction && dev->multifunction)
  138. + return 1;
  139. + }
  140. +
  141. + return -ENOTTY;
  142. +}
  143. +
  144. /*
  145. * Some NVIDIA GPU devices do not work with bus reset, SBR needs to be
  146. * prevented for those affected devices.
  147. @@ -4980,6 +5081,7 @@ static const struct pci_dev_acs_enabled {
  148. { PCI_VENDOR_ID_ZHAOXIN, PCI_ANY_ID, pci_quirk_zhaoxin_pcie_ports_acs },
  149. /* Wangxun nics */
  150. { PCI_VENDOR_ID_WANGXUN, PCI_ANY_ID, pci_quirk_wangxun_nic_acs },
  151. + { PCI_ANY_ID, PCI_ANY_ID, pcie_acs_overrides },
  152. { 0 }
  153. };