8138-pci-layerscape-add-MSI-interrupt-support.patch 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. From b0e74277164b17bb0d207ffe16056e13e558f6ba Mon Sep 17 00:00:00 2001
  2. From: Zhao Qiang <qiang.zhao@nxp.com>
  3. Date: Tue, 11 Oct 2016 16:25:07 +0800
  4. Subject: [PATCH 138/141] pci-layerscape: add MSI interrupt support
  5. Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com>
  6. ---
  7. drivers/iommu/amd_iommu.c | 5 +++--
  8. drivers/iommu/arm-smmu.c | 21 ++++++++++++++++++
  9. drivers/iommu/iommu.c | 8 +++----
  10. drivers/pci/host/pci-layerscape.c | 43 +++++++++++++++++++++++++++++++++++++
  11. drivers/pci/host/pci-layerscape.h | 17 +++++++++++++++
  12. drivers/pci/quirks.c | 19 +++++++++-------
  13. drivers/pci/search.c | 5 ++---
  14. include/linux/pci.h | 6 +++---
  15. 8 files changed, 104 insertions(+), 20 deletions(-)
  16. create mode 100644 drivers/pci/host/pci-layerscape.h
  17. --- a/drivers/iommu/amd_iommu.c
  18. +++ b/drivers/iommu/amd_iommu.c
  19. @@ -222,8 +222,9 @@ static u16 get_alias(struct device *dev)
  20. */
  21. if (pci_alias == devid &&
  22. PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
  23. - pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
  24. - pdev->dma_alias_devfn = ivrs_alias & 0xff;
  25. + pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
  26. + pdev->dma_alias_devid = PCI_DEVID(pdev->bus->number,
  27. + ivrs_alias & 0xff);
  28. pr_info("AMD-Vi: Added PCI DMA alias %02x.%d for %s\n",
  29. PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias),
  30. dev_name(dev));
  31. --- a/drivers/iommu/arm-smmu.c
  32. +++ b/drivers/iommu/arm-smmu.c
  33. @@ -45,6 +45,10 @@
  34. #include <linux/amba/bus.h>
  35. +#ifdef CONFIG_PCI_LAYERSCAPE
  36. +#include <../drivers/pci/host/pci-layerscape.h>
  37. +#endif
  38. +
  39. #include "io-pgtable.h"
  40. /* Maximum number of stream IDs assigned to a single device */
  41. @@ -1352,6 +1356,23 @@ static int arm_smmu_init_platform_device
  42. static int arm_smmu_add_device(struct device *dev)
  43. {
  44. struct iommu_group *group;
  45. +#ifdef CONFIG_PCI_LAYERSCAPE
  46. + u16 sid;
  47. + u32 streamid;
  48. + struct pci_dev *pdev;
  49. + if (dev_is_pci(dev)) {
  50. + pdev = to_pci_dev(dev);
  51. +
  52. + pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid, &sid);
  53. + streamid = set_pcie_streamid_translation(pdev, sid);
  54. + if (~streamid == 0) {
  55. + return -ENODEV;
  56. + }
  57. +
  58. + pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
  59. + pdev->dma_alias_devid = streamid;
  60. + }
  61. +#endif
  62. group = iommu_group_get_for_dev(dev);
  63. if (IS_ERR(group))
  64. --- a/drivers/iommu/iommu.c
  65. +++ b/drivers/iommu/iommu.c
  66. @@ -697,10 +697,10 @@ static struct iommu_group *get_pci_alias
  67. continue;
  68. /* We alias them or they alias us */
  69. - if (((pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) &&
  70. - pdev->dma_alias_devfn == tmp->devfn) ||
  71. - ((tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) &&
  72. - tmp->dma_alias_devfn == pdev->devfn)) {
  73. + if (((pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVID) &&
  74. + (pdev->dma_alias_devid & 0xff) == tmp->devfn) ||
  75. + ((tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVID) &&
  76. + (tmp->dma_alias_devid & 0xff) == pdev->devfn)) {
  77. group = get_pci_alias_group(tmp, devfns);
  78. if (group) {
  79. --- a/drivers/pci/host/pci-layerscape.c
  80. +++ b/drivers/pci/host/pci-layerscape.c
  81. @@ -37,6 +37,11 @@
  82. /* PEX LUT registers */
  83. #define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug Register */
  84. +#define PCIE_LUT_UDR(n) (0x800 + (n) * 8)
  85. +#define PCIE_LUT_LDR(n) (0x804 + (n) * 8)
  86. +#define PCIE_LUT_MASK_ALL 0xffff
  87. +#define PCIE_LUT_DR_NUM 32
  88. +#define PCIE_LUT_ENABLE (1 << 31)
  89. struct ls_pcie_drvdata {
  90. u32 lut_offset;
  91. @@ -52,10 +57,30 @@ struct ls_pcie {
  92. struct pcie_port pp;
  93. const struct ls_pcie_drvdata *drvdata;
  94. int index;
  95. + const u32 *avail_streamids;
  96. + int streamid_index;
  97. };
  98. #define to_ls_pcie(x) container_of(x, struct ls_pcie, pp)
  99. +u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid)
  100. +{
  101. + u32 index, streamid;
  102. + struct pcie_port *pp = pdev->bus->sysdata;
  103. + struct ls_pcie *pcie = to_ls_pcie(pp);
  104. +
  105. + if (!pcie->avail_streamids || !pcie->streamid_index)
  106. + return ~(u32)0;
  107. +
  108. + index = --pcie->streamid_index;
  109. + /* mask is set as all zeroes, want to match all bits */
  110. + iowrite32((devid << 16), pcie->lut + PCIE_LUT_UDR(index));
  111. + streamid = be32_to_cpup(&pcie->avail_streamids[index]);
  112. + iowrite32(streamid | PCIE_LUT_ENABLE, pcie->lut + PCIE_LUT_LDR(index));
  113. +
  114. + return streamid;
  115. +}
  116. +
  117. static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
  118. {
  119. u32 header_type;
  120. @@ -284,10 +309,28 @@ static int __init ls_pcie_probe(struct p
  121. pcie->drvdata = match->data;
  122. pcie->lut = pcie->dbi + pcie->drvdata->lut_offset;
  123. + /* Disable LDR zero */
  124. + iowrite32(0, pcie->lut + PCIE_LUT_LDR(0));
  125. if (!ls_pcie_is_bridge(pcie))
  126. return -ENODEV;
  127. + if (of_device_is_compatible(pdev->dev.of_node, "fsl,ls2085a-pcie") ||
  128. + of_device_is_compatible(pdev->dev.of_node, "fsl,ls2080a-pcie") ||
  129. + of_device_is_compatible(pdev->dev.of_node, "fsl,ls1088a-pcie")) {
  130. + int len;
  131. + const u32 *prop;
  132. + struct device_node *np;
  133. +
  134. + np = pdev->dev.of_node;
  135. + prop = (u32 *)of_get_property(np, "available-stream-ids", &len);
  136. + if (prop) {
  137. + pcie->avail_streamids = prop;
  138. + pcie->streamid_index = len/sizeof(u32);
  139. + } else
  140. + dev_err(&pdev->dev, "PCIe endpoint partitioning not possible\n");
  141. + }
  142. +
  143. ret = ls_add_pcie_port(&pcie->pp, pdev);
  144. if (ret < 0)
  145. return ret;
  146. --- /dev/null
  147. +++ b/drivers/pci/host/pci-layerscape.h
  148. @@ -0,0 +1,17 @@
  149. +/*
  150. + * Copyright (C) 2015 Freescale Semiconductor.
  151. + *
  152. + * Author: Varun Sethi <Varun.Sethi@freescale.com>
  153. + *
  154. + * This program is free software; you can redistribute it and/or modify
  155. + * it under the terms of the GNU General Public License version 2 as
  156. + * published by the Free Software Foundation.
  157. + */
  158. +
  159. +#ifndef _PCI_LAYERSCAPE_H
  160. +#define _PCI_LAYERSCAPE_H
  161. +
  162. +/* function for setting up stream id to device id translation */
  163. +u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid);
  164. +
  165. +#endif /* _PCI_LAYERSCAPE_H */
  166. --- a/drivers/pci/quirks.c
  167. +++ b/drivers/pci/quirks.c
  168. @@ -3594,8 +3594,9 @@ int pci_dev_specific_reset(struct pci_de
  169. static void quirk_dma_func0_alias(struct pci_dev *dev)
  170. {
  171. if (PCI_FUNC(dev->devfn) != 0) {
  172. - dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
  173. - dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
  174. + dev->dma_alias_devid = PCI_DEVID(dev->bus->number,
  175. + PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
  176. + dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
  177. }
  178. }
  179. @@ -3610,8 +3611,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_R
  180. static void quirk_dma_func1_alias(struct pci_dev *dev)
  181. {
  182. if (PCI_FUNC(dev->devfn) != 1) {
  183. - dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 1);
  184. - dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
  185. + dev->dma_alias_devid = PCI_DEVID(dev->bus->number,
  186. + PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
  187. + dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
  188. }
  189. }
  190. @@ -3684,11 +3686,12 @@ static void quirk_fixed_dma_alias(struct
  191. id = pci_match_id(fixed_dma_alias_tbl, dev);
  192. if (id) {
  193. - dev->dma_alias_devfn = id->driver_data;
  194. - dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
  195. + dev->dma_alias_devid = PCI_DEVID(dev->bus->number,
  196. + id->driver_data);
  197. + dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
  198. dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n",
  199. - PCI_SLOT(dev->dma_alias_devfn),
  200. - PCI_FUNC(dev->dma_alias_devfn));
  201. + PCI_SLOT(dev->dma_alias_devid),
  202. + PCI_FUNC(dev->dma_alias_devid));
  203. }
  204. }
  205. --- a/drivers/pci/search.c
  206. +++ b/drivers/pci/search.c
  207. @@ -40,9 +40,8 @@ int pci_for_each_dma_alias(struct pci_de
  208. * If the device is broken and uses an alias requester ID for
  209. * DMA, iterate over that too.
  210. */
  211. - if (unlikely(pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN)) {
  212. - ret = fn(pdev, PCI_DEVID(pdev->bus->number,
  213. - pdev->dma_alias_devfn), data);
  214. + if (unlikely(pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVID)) {
  215. + ret = fn(pdev, pdev->dma_alias_devid, data);
  216. if (ret)
  217. return ret;
  218. }
  219. --- a/include/linux/pci.h
  220. +++ b/include/linux/pci.h
  221. @@ -172,8 +172,8 @@ enum pci_dev_flags {
  222. PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) (1 << 2),
  223. /* Flag for quirk use to store if quirk-specific ACS is enabled */
  224. PCI_DEV_FLAGS_ACS_ENABLED_QUIRK = (__force pci_dev_flags_t) (1 << 3),
  225. - /* Flag to indicate the device uses dma_alias_devfn */
  226. - PCI_DEV_FLAGS_DMA_ALIAS_DEVFN = (__force pci_dev_flags_t) (1 << 4),
  227. + /* Flag to indicate the device uses dma_alias_devid */
  228. + PCI_DEV_FLAGS_DMA_ALIAS_DEVID = (__force pci_dev_flags_t) (1 << 4),
  229. /* Use a PCIe-to-PCI bridge alias even if !pci_is_pcie */
  230. PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS = (__force pci_dev_flags_t) (1 << 5),
  231. /* Do not use bus resets for device */
  232. @@ -279,7 +279,7 @@ struct pci_dev {
  233. u8 rom_base_reg; /* which config register controls the ROM */
  234. u8 pin; /* which interrupt pin this device uses */
  235. u16 pcie_flags_reg; /* cached PCIe Capabilities Register */
  236. - u8 dma_alias_devfn;/* devfn of DMA alias, if any */
  237. + u32 dma_alias_devid;/* devid of DMA alias */
  238. struct pci_driver *driver; /* which driver has allocated this device */
  239. u64 dma_mask; /* Mask of the bits of bus address this