dfl-pci.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for FPGA Device Feature List (DFL) PCIe device
  4. *
  5. * Copyright (C) 2017-2018 Intel Corporation, Inc.
  6. *
  7. * Authors:
  8. * Zhang Yi <Yi.Z.Zhang@intel.com>
  9. * Xiao Guangrong <guangrong.xiao@linux.intel.com>
  10. * Joseph Grecco <joe.grecco@intel.com>
  11. * Enno Luebbers <enno.luebbers@intel.com>
  12. * Tim Whisonant <tim.whisonant@intel.com>
  13. * Ananda Ravuri <ananda.ravuri@intel.com>
  14. * Henry Mitchel <henry.mitchel@intel.com>
  15. */
  16. #include <linux/pci.h>
  17. #include <linux/types.h>
  18. #include <linux/kernel.h>
  19. #include <linux/module.h>
  20. #include <linux/stddef.h>
  21. #include <linux/errno.h>
  22. #include <linux/aer.h>
  23. #include "dfl.h"
  24. #define DRV_VERSION "0.8"
  25. #define DRV_NAME "dfl-pci"
  26. struct cci_drvdata {
  27. struct dfl_fpga_cdev *cdev; /* container device */
  28. };
  29. static void __iomem *cci_pci_ioremap_bar0(struct pci_dev *pcidev)
  30. {
  31. if (pcim_iomap_regions(pcidev, BIT(0), DRV_NAME))
  32. return NULL;
  33. return pcim_iomap_table(pcidev)[0];
  34. }
  35. static int cci_pci_alloc_irq(struct pci_dev *pcidev)
  36. {
  37. int ret, nvec = pci_msix_vec_count(pcidev);
  38. if (nvec <= 0) {
  39. dev_dbg(&pcidev->dev, "fpga interrupt not supported\n");
  40. return 0;
  41. }
  42. ret = pci_alloc_irq_vectors(pcidev, nvec, nvec, PCI_IRQ_MSIX);
  43. if (ret < 0)
  44. return ret;
  45. return nvec;
  46. }
  47. static void cci_pci_free_irq(struct pci_dev *pcidev)
  48. {
  49. pci_free_irq_vectors(pcidev);
  50. }
  51. /* PCI Device ID */
  52. #define PCIE_DEVICE_ID_PF_INT_5_X 0xBCBD
  53. #define PCIE_DEVICE_ID_PF_INT_6_X 0xBCC0
  54. #define PCIE_DEVICE_ID_PF_DSC_1_X 0x09C4
  55. #define PCIE_DEVICE_ID_INTEL_PAC_N3000 0x0B30
  56. #define PCIE_DEVICE_ID_INTEL_PAC_D5005 0x0B2B
  57. /* VF Device */
  58. #define PCIE_DEVICE_ID_VF_INT_5_X 0xBCBF
  59. #define PCIE_DEVICE_ID_VF_INT_6_X 0xBCC1
  60. #define PCIE_DEVICE_ID_VF_DSC_1_X 0x09C5
  61. #define PCIE_DEVICE_ID_INTEL_PAC_D5005_VF 0x0B2C
  62. static struct pci_device_id cci_pcie_id_tbl[] = {
  63. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_5_X),},
  64. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_INT_5_X),},
  65. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_6_X),},
  66. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_INT_6_X),},
  67. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_DSC_1_X),},
  68. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_DSC_1_X),},
  69. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_N3000),},
  70. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005),},
  71. {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005_VF),},
  72. {0,}
  73. };
  74. MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
  75. static int cci_init_drvdata(struct pci_dev *pcidev)
  76. {
  77. struct cci_drvdata *drvdata;
  78. drvdata = devm_kzalloc(&pcidev->dev, sizeof(*drvdata), GFP_KERNEL);
  79. if (!drvdata)
  80. return -ENOMEM;
  81. pci_set_drvdata(pcidev, drvdata);
  82. return 0;
  83. }
  84. static void cci_remove_feature_devs(struct pci_dev *pcidev)
  85. {
  86. struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
  87. /* remove all children feature devices */
  88. dfl_fpga_feature_devs_remove(drvdata->cdev);
  89. cci_pci_free_irq(pcidev);
  90. }
  91. static int *cci_pci_create_irq_table(struct pci_dev *pcidev, unsigned int nvec)
  92. {
  93. unsigned int i;
  94. int *table;
  95. table = kcalloc(nvec, sizeof(int), GFP_KERNEL);
  96. if (!table)
  97. return table;
  98. for (i = 0; i < nvec; i++)
  99. table[i] = pci_irq_vector(pcidev, i);
  100. return table;
  101. }
  102. /* enumerate feature devices under pci device */
  103. static int cci_enumerate_feature_devs(struct pci_dev *pcidev)
  104. {
  105. struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
  106. int port_num, bar, i, nvec, ret = 0;
  107. struct dfl_fpga_enum_info *info;
  108. struct dfl_fpga_cdev *cdev;
  109. resource_size_t start, len;
  110. void __iomem *base;
  111. int *irq_table;
  112. u32 offset;
  113. u64 v;
  114. /* allocate enumeration info via pci_dev */
  115. info = dfl_fpga_enum_info_alloc(&pcidev->dev);
  116. if (!info)
  117. return -ENOMEM;
  118. /* add irq info for enumeration if the device support irq */
  119. nvec = cci_pci_alloc_irq(pcidev);
  120. if (nvec < 0) {
  121. dev_err(&pcidev->dev, "Fail to alloc irq %d.\n", nvec);
  122. ret = nvec;
  123. goto enum_info_free_exit;
  124. } else if (nvec) {
  125. irq_table = cci_pci_create_irq_table(pcidev, nvec);
  126. if (!irq_table) {
  127. ret = -ENOMEM;
  128. goto irq_free_exit;
  129. }
  130. ret = dfl_fpga_enum_info_add_irq(info, nvec, irq_table);
  131. kfree(irq_table);
  132. if (ret)
  133. goto irq_free_exit;
  134. }
  135. /* start to find Device Feature List in Bar 0 */
  136. base = cci_pci_ioremap_bar0(pcidev);
  137. if (!base) {
  138. ret = -ENOMEM;
  139. goto irq_free_exit;
  140. }
  141. /*
  142. * PF device has FME and Ports/AFUs, and VF device only has one
  143. * Port/AFU. Check them and add related "Device Feature List" info
  144. * for the next step enumeration.
  145. */
  146. if (dfl_feature_is_fme(base)) {
  147. start = pci_resource_start(pcidev, 0);
  148. len = pci_resource_len(pcidev, 0);
  149. dfl_fpga_enum_info_add_dfl(info, start, len);
  150. /*
  151. * find more Device Feature Lists (e.g. Ports) per information
  152. * indicated by FME module.
  153. */
  154. v = readq(base + FME_HDR_CAP);
  155. port_num = FIELD_GET(FME_CAP_NUM_PORTS, v);
  156. WARN_ON(port_num > MAX_DFL_FPGA_PORT_NUM);
  157. for (i = 0; i < port_num; i++) {
  158. v = readq(base + FME_HDR_PORT_OFST(i));
  159. /* skip ports which are not implemented. */
  160. if (!(v & FME_PORT_OFST_IMP))
  161. continue;
  162. /*
  163. * add Port's Device Feature List information for next
  164. * step enumeration.
  165. */
  166. bar = FIELD_GET(FME_PORT_OFST_BAR_ID, v);
  167. offset = FIELD_GET(FME_PORT_OFST_DFH_OFST, v);
  168. start = pci_resource_start(pcidev, bar) + offset;
  169. len = pci_resource_len(pcidev, bar) - offset;
  170. dfl_fpga_enum_info_add_dfl(info, start, len);
  171. }
  172. } else if (dfl_feature_is_port(base)) {
  173. start = pci_resource_start(pcidev, 0);
  174. len = pci_resource_len(pcidev, 0);
  175. dfl_fpga_enum_info_add_dfl(info, start, len);
  176. } else {
  177. ret = -ENODEV;
  178. goto irq_free_exit;
  179. }
  180. /* release I/O mappings for next step enumeration */
  181. pcim_iounmap_regions(pcidev, BIT(0));
  182. /* start enumeration with prepared enumeration information */
  183. cdev = dfl_fpga_feature_devs_enumerate(info);
  184. if (IS_ERR(cdev)) {
  185. dev_err(&pcidev->dev, "Enumeration failure\n");
  186. ret = PTR_ERR(cdev);
  187. goto irq_free_exit;
  188. }
  189. drvdata->cdev = cdev;
  190. irq_free_exit:
  191. if (ret)
  192. cci_pci_free_irq(pcidev);
  193. enum_info_free_exit:
  194. dfl_fpga_enum_info_free(info);
  195. return ret;
  196. }
  197. static
  198. int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
  199. {
  200. int ret;
  201. ret = pcim_enable_device(pcidev);
  202. if (ret < 0) {
  203. dev_err(&pcidev->dev, "Failed to enable device %d.\n", ret);
  204. return ret;
  205. }
  206. ret = pci_enable_pcie_error_reporting(pcidev);
  207. if (ret && ret != -EINVAL)
  208. dev_info(&pcidev->dev, "PCIE AER unavailable %d.\n", ret);
  209. pci_set_master(pcidev);
  210. if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
  211. ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64));
  212. if (ret)
  213. goto disable_error_report_exit;
  214. } else if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(32))) {
  215. ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
  216. if (ret)
  217. goto disable_error_report_exit;
  218. } else {
  219. ret = -EIO;
  220. dev_err(&pcidev->dev, "No suitable DMA support available.\n");
  221. goto disable_error_report_exit;
  222. }
  223. ret = cci_init_drvdata(pcidev);
  224. if (ret) {
  225. dev_err(&pcidev->dev, "Fail to init drvdata %d.\n", ret);
  226. goto disable_error_report_exit;
  227. }
  228. ret = cci_enumerate_feature_devs(pcidev);
  229. if (!ret)
  230. return ret;
  231. dev_err(&pcidev->dev, "enumeration failure %d.\n", ret);
  232. disable_error_report_exit:
  233. pci_disable_pcie_error_reporting(pcidev);
  234. return ret;
  235. }
  236. static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
  237. {
  238. struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
  239. struct dfl_fpga_cdev *cdev = drvdata->cdev;
  240. if (!num_vfs) {
  241. /*
  242. * disable SRIOV and then put released ports back to default
  243. * PF access mode.
  244. */
  245. pci_disable_sriov(pcidev);
  246. dfl_fpga_cdev_config_ports_pf(cdev);
  247. } else {
  248. int ret;
  249. /*
  250. * before enable SRIOV, put released ports into VF access mode
  251. * first of all.
  252. */
  253. ret = dfl_fpga_cdev_config_ports_vf(cdev, num_vfs);
  254. if (ret)
  255. return ret;
  256. ret = pci_enable_sriov(pcidev, num_vfs);
  257. if (ret) {
  258. dfl_fpga_cdev_config_ports_pf(cdev);
  259. return ret;
  260. }
  261. }
  262. return num_vfs;
  263. }
  264. static void cci_pci_remove(struct pci_dev *pcidev)
  265. {
  266. if (dev_is_pf(&pcidev->dev))
  267. cci_pci_sriov_configure(pcidev, 0);
  268. cci_remove_feature_devs(pcidev);
  269. pci_disable_pcie_error_reporting(pcidev);
  270. }
  271. static struct pci_driver cci_pci_driver = {
  272. .name = DRV_NAME,
  273. .id_table = cci_pcie_id_tbl,
  274. .probe = cci_pci_probe,
  275. .remove = cci_pci_remove,
  276. .sriov_configure = cci_pci_sriov_configure,
  277. };
  278. module_pci_driver(cci_pci_driver);
  279. MODULE_DESCRIPTION("FPGA DFL PCIe Device Driver");
  280. MODULE_AUTHOR("Intel Corporation");
  281. MODULE_LICENSE("GPL v2");