pci_endpoint_test.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /**
  2. * Host side test driver to test endpoint functionality
  3. *
  4. * Copyright (C) 2017 Texas Instruments
  5. * Author: Kishon Vijay Abraham I <kishon@ti.com>
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 of
  9. * the License as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <linux/crc32.h>
  20. #include <linux/delay.h>
  21. #include <linux/fs.h>
  22. #include <linux/io.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/irq.h>
  25. #include <linux/miscdevice.h>
  26. #include <linux/module.h>
  27. #include <linux/mutex.h>
  28. #include <linux/random.h>
  29. #include <linux/slab.h>
  30. #include <linux/pci.h>
  31. #include <linux/pci_ids.h>
  32. #include <linux/pci_regs.h>
  33. #include <uapi/linux/pcitest.h>
  34. #define DRV_MODULE_NAME "pci-endpoint-test"
  35. #define PCI_ENDPOINT_TEST_MAGIC 0x0
  36. #define PCI_ENDPOINT_TEST_COMMAND 0x4
  37. #define COMMAND_RAISE_LEGACY_IRQ BIT(0)
  38. #define COMMAND_RAISE_MSI_IRQ BIT(1)
  39. #define MSI_NUMBER_SHIFT 2
  40. /* 6 bits for MSI number */
  41. #define COMMAND_READ BIT(8)
  42. #define COMMAND_WRITE BIT(9)
  43. #define COMMAND_COPY BIT(10)
  44. #define PCI_ENDPOINT_TEST_STATUS 0x8
  45. #define STATUS_READ_SUCCESS BIT(0)
  46. #define STATUS_READ_FAIL BIT(1)
  47. #define STATUS_WRITE_SUCCESS BIT(2)
  48. #define STATUS_WRITE_FAIL BIT(3)
  49. #define STATUS_COPY_SUCCESS BIT(4)
  50. #define STATUS_COPY_FAIL BIT(5)
  51. #define STATUS_IRQ_RAISED BIT(6)
  52. #define STATUS_SRC_ADDR_INVALID BIT(7)
  53. #define STATUS_DST_ADDR_INVALID BIT(8)
  54. #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0xc
  55. #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10
  56. #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14
  57. #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18
  58. #define PCI_ENDPOINT_TEST_SIZE 0x1c
  59. #define PCI_ENDPOINT_TEST_CHECKSUM 0x20
  60. static DEFINE_IDA(pci_endpoint_test_ida);
  61. #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
  62. miscdev)
  63. enum pci_barno {
  64. BAR_0,
  65. BAR_1,
  66. BAR_2,
  67. BAR_3,
  68. BAR_4,
  69. BAR_5,
  70. };
  71. struct pci_endpoint_test {
  72. struct pci_dev *pdev;
  73. void __iomem *base;
  74. void __iomem *bar[6];
  75. struct completion irq_raised;
  76. int last_irq;
  77. /* mutex to protect the ioctls */
  78. struct mutex mutex;
  79. struct miscdevice miscdev;
  80. };
  81. static int bar_size[] = { 4, 512, 1024, 16384, 131072, 1048576 };
  82. static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
  83. u32 offset)
  84. {
  85. return readl(test->base + offset);
  86. }
  87. static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
  88. u32 offset, u32 value)
  89. {
  90. writel(value, test->base + offset);
  91. }
  92. static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test,
  93. int bar, int offset)
  94. {
  95. return readl(test->bar[bar] + offset);
  96. }
  97. static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test,
  98. int bar, u32 offset, u32 value)
  99. {
  100. writel(value, test->bar[bar] + offset);
  101. }
  102. static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
  103. {
  104. struct pci_endpoint_test *test = dev_id;
  105. u32 reg;
  106. reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
  107. if (reg & STATUS_IRQ_RAISED) {
  108. test->last_irq = irq;
  109. complete(&test->irq_raised);
  110. reg &= ~STATUS_IRQ_RAISED;
  111. }
  112. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS,
  113. reg);
  114. return IRQ_HANDLED;
  115. }
  116. static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
  117. enum pci_barno barno)
  118. {
  119. int j;
  120. u32 val;
  121. int size;
  122. if (!test->bar[barno])
  123. return false;
  124. size = bar_size[barno];
  125. for (j = 0; j < size; j += 4)
  126. pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
  127. for (j = 0; j < size; j += 4) {
  128. val = pci_endpoint_test_bar_readl(test, barno, j);
  129. if (val != 0xA0A0A0A0)
  130. return false;
  131. }
  132. return true;
  133. }
  134. static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
  135. {
  136. u32 val;
  137. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
  138. COMMAND_RAISE_LEGACY_IRQ);
  139. val = wait_for_completion_timeout(&test->irq_raised,
  140. msecs_to_jiffies(1000));
  141. if (!val)
  142. return false;
  143. return true;
  144. }
  145. static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
  146. u8 msi_num)
  147. {
  148. u32 val;
  149. struct pci_dev *pdev = test->pdev;
  150. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
  151. msi_num << MSI_NUMBER_SHIFT |
  152. COMMAND_RAISE_MSI_IRQ);
  153. val = wait_for_completion_timeout(&test->irq_raised,
  154. msecs_to_jiffies(1000));
  155. if (!val)
  156. return false;
  157. if (test->last_irq - pdev->irq == msi_num - 1)
  158. return true;
  159. return false;
  160. }
  161. static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
  162. {
  163. bool ret = false;
  164. void *src_addr;
  165. void *dst_addr;
  166. dma_addr_t src_phys_addr;
  167. dma_addr_t dst_phys_addr;
  168. struct pci_dev *pdev = test->pdev;
  169. struct device *dev = &pdev->dev;
  170. u32 src_crc32;
  171. u32 dst_crc32;
  172. src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL);
  173. if (!src_addr) {
  174. dev_err(dev, "failed to allocate source buffer\n");
  175. ret = false;
  176. goto err;
  177. }
  178. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
  179. lower_32_bits(src_phys_addr));
  180. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
  181. upper_32_bits(src_phys_addr));
  182. get_random_bytes(src_addr, size);
  183. src_crc32 = crc32_le(~0, src_addr, size);
  184. dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL);
  185. if (!dst_addr) {
  186. dev_err(dev, "failed to allocate destination address\n");
  187. ret = false;
  188. goto err_src_addr;
  189. }
  190. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
  191. lower_32_bits(dst_phys_addr));
  192. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
  193. upper_32_bits(dst_phys_addr));
  194. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE,
  195. size);
  196. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
  197. 1 << MSI_NUMBER_SHIFT | COMMAND_COPY);
  198. wait_for_completion(&test->irq_raised);
  199. dst_crc32 = crc32_le(~0, dst_addr, size);
  200. if (dst_crc32 == src_crc32)
  201. ret = true;
  202. dma_free_coherent(dev, size, dst_addr, dst_phys_addr);
  203. err_src_addr:
  204. dma_free_coherent(dev, size, src_addr, src_phys_addr);
  205. err:
  206. return ret;
  207. }
  208. static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
  209. {
  210. bool ret = false;
  211. u32 reg;
  212. void *addr;
  213. dma_addr_t phys_addr;
  214. struct pci_dev *pdev = test->pdev;
  215. struct device *dev = &pdev->dev;
  216. u32 crc32;
  217. addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
  218. if (!addr) {
  219. dev_err(dev, "failed to allocate address\n");
  220. ret = false;
  221. goto err;
  222. }
  223. get_random_bytes(addr, size);
  224. crc32 = crc32_le(~0, addr, size);
  225. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM,
  226. crc32);
  227. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
  228. lower_32_bits(phys_addr));
  229. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
  230. upper_32_bits(phys_addr));
  231. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
  232. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
  233. 1 << MSI_NUMBER_SHIFT | COMMAND_READ);
  234. wait_for_completion(&test->irq_raised);
  235. reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
  236. if (reg & STATUS_READ_SUCCESS)
  237. ret = true;
  238. dma_free_coherent(dev, size, addr, phys_addr);
  239. err:
  240. return ret;
  241. }
  242. static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
  243. {
  244. bool ret = false;
  245. void *addr;
  246. dma_addr_t phys_addr;
  247. struct pci_dev *pdev = test->pdev;
  248. struct device *dev = &pdev->dev;
  249. u32 crc32;
  250. addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
  251. if (!addr) {
  252. dev_err(dev, "failed to allocate destination address\n");
  253. ret = false;
  254. goto err;
  255. }
  256. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
  257. lower_32_bits(phys_addr));
  258. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
  259. upper_32_bits(phys_addr));
  260. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
  261. pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
  262. 1 << MSI_NUMBER_SHIFT | COMMAND_WRITE);
  263. wait_for_completion(&test->irq_raised);
  264. crc32 = crc32_le(~0, addr, size);
  265. if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
  266. ret = true;
  267. dma_free_coherent(dev, size, addr, phys_addr);
  268. err:
  269. return ret;
  270. }
  271. static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
  272. unsigned long arg)
  273. {
  274. int ret = -EINVAL;
  275. enum pci_barno bar;
  276. struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
  277. mutex_lock(&test->mutex);
  278. switch (cmd) {
  279. case PCITEST_BAR:
  280. bar = arg;
  281. if (bar < 0 || bar > 5)
  282. goto ret;
  283. ret = pci_endpoint_test_bar(test, bar);
  284. break;
  285. case PCITEST_LEGACY_IRQ:
  286. ret = pci_endpoint_test_legacy_irq(test);
  287. break;
  288. case PCITEST_MSI:
  289. ret = pci_endpoint_test_msi_irq(test, arg);
  290. break;
  291. case PCITEST_WRITE:
  292. ret = pci_endpoint_test_write(test, arg);
  293. break;
  294. case PCITEST_READ:
  295. ret = pci_endpoint_test_read(test, arg);
  296. break;
  297. case PCITEST_COPY:
  298. ret = pci_endpoint_test_copy(test, arg);
  299. break;
  300. }
  301. ret:
  302. mutex_unlock(&test->mutex);
  303. return ret;
  304. }
  305. static const struct file_operations pci_endpoint_test_fops = {
  306. .owner = THIS_MODULE,
  307. .unlocked_ioctl = pci_endpoint_test_ioctl,
  308. };
  309. static int pci_endpoint_test_probe(struct pci_dev *pdev,
  310. const struct pci_device_id *ent)
  311. {
  312. int i;
  313. int err;
  314. int irq;
  315. int id;
  316. char name[20];
  317. enum pci_barno bar;
  318. void __iomem *base;
  319. struct device *dev = &pdev->dev;
  320. struct pci_endpoint_test *test;
  321. struct miscdevice *misc_device;
  322. if (pci_is_bridge(pdev))
  323. return -ENODEV;
  324. test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL);
  325. if (!test)
  326. return -ENOMEM;
  327. test->pdev = pdev;
  328. init_completion(&test->irq_raised);
  329. mutex_init(&test->mutex);
  330. err = pci_enable_device(pdev);
  331. if (err) {
  332. dev_err(dev, "Cannot enable PCI device\n");
  333. return err;
  334. }
  335. err = pci_request_regions(pdev, DRV_MODULE_NAME);
  336. if (err) {
  337. dev_err(dev, "Cannot obtain PCI resources\n");
  338. goto err_disable_pdev;
  339. }
  340. pci_set_master(pdev);
  341. irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
  342. if (irq < 0)
  343. dev_err(dev, "failed to get MSI interrupts\n");
  344. err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
  345. IRQF_SHARED, DRV_MODULE_NAME, test);
  346. if (err) {
  347. dev_err(dev, "failed to request IRQ %d\n", pdev->irq);
  348. goto err_disable_msi;
  349. }
  350. for (i = 1; i < irq; i++) {
  351. err = devm_request_irq(dev, pdev->irq + i,
  352. pci_endpoint_test_irqhandler,
  353. IRQF_SHARED, DRV_MODULE_NAME, test);
  354. if (err)
  355. dev_err(dev, "failed to request IRQ %d for MSI %d\n",
  356. pdev->irq + i, i + 1);
  357. }
  358. for (bar = BAR_0; bar <= BAR_5; bar++) {
  359. base = pci_ioremap_bar(pdev, bar);
  360. if (!base) {
  361. dev_err(dev, "failed to read BAR%d\n", bar);
  362. WARN_ON(bar == BAR_0);
  363. }
  364. test->bar[bar] = base;
  365. }
  366. test->base = test->bar[0];
  367. if (!test->base) {
  368. dev_err(dev, "Cannot perform PCI test without BAR0\n");
  369. goto err_iounmap;
  370. }
  371. pci_set_drvdata(pdev, test);
  372. id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
  373. if (id < 0) {
  374. dev_err(dev, "unable to get id\n");
  375. goto err_iounmap;
  376. }
  377. snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
  378. misc_device = &test->miscdev;
  379. misc_device->minor = MISC_DYNAMIC_MINOR;
  380. misc_device->name = name;
  381. misc_device->fops = &pci_endpoint_test_fops,
  382. err = misc_register(misc_device);
  383. if (err) {
  384. dev_err(dev, "failed to register device\n");
  385. goto err_ida_remove;
  386. }
  387. return 0;
  388. err_ida_remove:
  389. ida_simple_remove(&pci_endpoint_test_ida, id);
  390. err_iounmap:
  391. for (bar = BAR_0; bar <= BAR_5; bar++) {
  392. if (test->bar[bar])
  393. pci_iounmap(pdev, test->bar[bar]);
  394. }
  395. err_disable_msi:
  396. pci_disable_msi(pdev);
  397. pci_release_regions(pdev);
  398. err_disable_pdev:
  399. pci_disable_device(pdev);
  400. return err;
  401. }
  402. static void pci_endpoint_test_remove(struct pci_dev *pdev)
  403. {
  404. int id;
  405. enum pci_barno bar;
  406. struct pci_endpoint_test *test = pci_get_drvdata(pdev);
  407. struct miscdevice *misc_device = &test->miscdev;
  408. if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
  409. return;
  410. misc_deregister(&test->miscdev);
  411. ida_simple_remove(&pci_endpoint_test_ida, id);
  412. for (bar = BAR_0; bar <= BAR_5; bar++) {
  413. if (test->bar[bar])
  414. pci_iounmap(pdev, test->bar[bar]);
  415. }
  416. pci_disable_msi(pdev);
  417. pci_release_regions(pdev);
  418. pci_disable_device(pdev);
  419. }
  420. static const struct pci_device_id pci_endpoint_test_tbl[] = {
  421. { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) },
  422. { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) },
  423. { }
  424. };
  425. MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
  426. static struct pci_driver pci_endpoint_test_driver = {
  427. .name = DRV_MODULE_NAME,
  428. .id_table = pci_endpoint_test_tbl,
  429. .probe = pci_endpoint_test_probe,
  430. .remove = pci_endpoint_test_remove,
  431. };
  432. module_pci_driver(pci_endpoint_test_driver);
  433. MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER");
  434. MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
  435. MODULE_LICENSE("GPL v2");