pcitest.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /**
  3. * Userspace PCI Endpoint Test Module
  4. *
  5. * Copyright (C) 2017 Texas Instruments
  6. * Author: Kishon Vijay Abraham I <kishon@ti.com>
  7. */
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <stdbool.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <sys/ioctl.h>
  14. #include <unistd.h>
  15. #include <linux/pcitest.h>
  16. static char *result[] = { "NOT OKAY", "OKAY" };
  17. static char *irq[] = { "LEGACY", "MSI", "MSI-X" };
  18. struct pci_test {
  19. char *device;
  20. char barnum;
  21. bool legacyirq;
  22. unsigned int msinum;
  23. unsigned int msixnum;
  24. int irqtype;
  25. bool set_irqtype;
  26. bool get_irqtype;
  27. bool clear_irq;
  28. bool read;
  29. bool write;
  30. bool copy;
  31. unsigned long size;
  32. bool use_dma;
  33. };
  34. static int run_test(struct pci_test *test)
  35. {
  36. struct pci_endpoint_test_xfer_param param = {};
  37. int ret = -EINVAL;
  38. int fd;
  39. fd = open(test->device, O_RDWR);
  40. if (fd < 0) {
  41. perror("can't open PCI Endpoint Test device");
  42. return -ENODEV;
  43. }
  44. if (test->barnum >= 0 && test->barnum <= 5) {
  45. ret = ioctl(fd, PCITEST_BAR, test->barnum);
  46. fprintf(stdout, "BAR%d:\t\t", test->barnum);
  47. if (ret < 0)
  48. fprintf(stdout, "TEST FAILED\n");
  49. else
  50. fprintf(stdout, "%s\n", result[ret]);
  51. }
  52. if (test->set_irqtype) {
  53. ret = ioctl(fd, PCITEST_SET_IRQTYPE, test->irqtype);
  54. fprintf(stdout, "SET IRQ TYPE TO %s:\t\t", irq[test->irqtype]);
  55. if (ret < 0)
  56. fprintf(stdout, "FAILED\n");
  57. else
  58. fprintf(stdout, "%s\n", result[ret]);
  59. }
  60. if (test->get_irqtype) {
  61. ret = ioctl(fd, PCITEST_GET_IRQTYPE);
  62. fprintf(stdout, "GET IRQ TYPE:\t\t");
  63. if (ret < 0)
  64. fprintf(stdout, "FAILED\n");
  65. else
  66. fprintf(stdout, "%s\n", irq[ret]);
  67. }
  68. if (test->clear_irq) {
  69. ret = ioctl(fd, PCITEST_CLEAR_IRQ);
  70. fprintf(stdout, "CLEAR IRQ:\t\t");
  71. if (ret < 0)
  72. fprintf(stdout, "FAILED\n");
  73. else
  74. fprintf(stdout, "%s\n", result[ret]);
  75. }
  76. if (test->legacyirq) {
  77. ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0);
  78. fprintf(stdout, "LEGACY IRQ:\t");
  79. if (ret < 0)
  80. fprintf(stdout, "TEST FAILED\n");
  81. else
  82. fprintf(stdout, "%s\n", result[ret]);
  83. }
  84. if (test->msinum > 0 && test->msinum <= 32) {
  85. ret = ioctl(fd, PCITEST_MSI, test->msinum);
  86. fprintf(stdout, "MSI%d:\t\t", test->msinum);
  87. if (ret < 0)
  88. fprintf(stdout, "TEST FAILED\n");
  89. else
  90. fprintf(stdout, "%s\n", result[ret]);
  91. }
  92. if (test->msixnum > 0 && test->msixnum <= 2048) {
  93. ret = ioctl(fd, PCITEST_MSIX, test->msixnum);
  94. fprintf(stdout, "MSI-X%d:\t\t", test->msixnum);
  95. if (ret < 0)
  96. fprintf(stdout, "TEST FAILED\n");
  97. else
  98. fprintf(stdout, "%s\n", result[ret]);
  99. }
  100. if (test->write) {
  101. param.size = test->size;
  102. if (test->use_dma)
  103. param.flags = PCITEST_FLAGS_USE_DMA;
  104. ret = ioctl(fd, PCITEST_WRITE, &param);
  105. fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size);
  106. if (ret < 0)
  107. fprintf(stdout, "TEST FAILED\n");
  108. else
  109. fprintf(stdout, "%s\n", result[ret]);
  110. }
  111. if (test->read) {
  112. param.size = test->size;
  113. if (test->use_dma)
  114. param.flags = PCITEST_FLAGS_USE_DMA;
  115. ret = ioctl(fd, PCITEST_READ, &param);
  116. fprintf(stdout, "READ (%7ld bytes):\t\t", test->size);
  117. if (ret < 0)
  118. fprintf(stdout, "TEST FAILED\n");
  119. else
  120. fprintf(stdout, "%s\n", result[ret]);
  121. }
  122. if (test->copy) {
  123. param.size = test->size;
  124. if (test->use_dma)
  125. param.flags = PCITEST_FLAGS_USE_DMA;
  126. ret = ioctl(fd, PCITEST_COPY, &param);
  127. fprintf(stdout, "COPY (%7ld bytes):\t\t", test->size);
  128. if (ret < 0)
  129. fprintf(stdout, "TEST FAILED\n");
  130. else
  131. fprintf(stdout, "%s\n", result[ret]);
  132. }
  133. fflush(stdout);
  134. close(fd);
  135. return (ret < 0) ? ret : 1 - ret; /* return 0 if test succeeded */
  136. }
  137. int main(int argc, char **argv)
  138. {
  139. int c;
  140. struct pci_test *test;
  141. test = calloc(1, sizeof(*test));
  142. if (!test) {
  143. perror("Fail to allocate memory for pci_test\n");
  144. return -ENOMEM;
  145. }
  146. /* since '0' is a valid BAR number, initialize it to -1 */
  147. test->barnum = -1;
  148. /* set default size as 100KB */
  149. test->size = 0x19000;
  150. /* set default endpoint device */
  151. test->device = "/dev/pci-endpoint-test.0";
  152. while ((c = getopt(argc, argv, "D:b:m:x:i:deIlhrwcs:")) != EOF)
  153. switch (c) {
  154. case 'D':
  155. test->device = optarg;
  156. continue;
  157. case 'b':
  158. test->barnum = atoi(optarg);
  159. if (test->barnum < 0 || test->barnum > 5)
  160. goto usage;
  161. continue;
  162. case 'l':
  163. test->legacyirq = true;
  164. continue;
  165. case 'm':
  166. test->msinum = atoi(optarg);
  167. if (test->msinum < 1 || test->msinum > 32)
  168. goto usage;
  169. continue;
  170. case 'x':
  171. test->msixnum = atoi(optarg);
  172. if (test->msixnum < 1 || test->msixnum > 2048)
  173. goto usage;
  174. continue;
  175. case 'i':
  176. test->irqtype = atoi(optarg);
  177. if (test->irqtype < 0 || test->irqtype > 2)
  178. goto usage;
  179. test->set_irqtype = true;
  180. continue;
  181. case 'I':
  182. test->get_irqtype = true;
  183. continue;
  184. case 'r':
  185. test->read = true;
  186. continue;
  187. case 'w':
  188. test->write = true;
  189. continue;
  190. case 'c':
  191. test->copy = true;
  192. continue;
  193. case 'e':
  194. test->clear_irq = true;
  195. continue;
  196. case 's':
  197. test->size = strtoul(optarg, NULL, 0);
  198. continue;
  199. case 'd':
  200. test->use_dma = true;
  201. continue;
  202. case 'h':
  203. default:
  204. usage:
  205. fprintf(stderr,
  206. "usage: %s [options]\n"
  207. "Options:\n"
  208. "\t-D <dev> PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n"
  209. "\t-b <bar num> BAR test (bar number between 0..5)\n"
  210. "\t-m <msi num> MSI test (msi number between 1..32)\n"
  211. "\t-x <msix num> \tMSI-X test (msix number between 1..2048)\n"
  212. "\t-i <irq type> \tSet IRQ type (0 - Legacy, 1 - MSI, 2 - MSI-X)\n"
  213. "\t-e Clear IRQ\n"
  214. "\t-I Get current IRQ type configured\n"
  215. "\t-d Use DMA\n"
  216. "\t-l Legacy IRQ test\n"
  217. "\t-r Read buffer test\n"
  218. "\t-w Write buffer test\n"
  219. "\t-c Copy buffer test\n"
  220. "\t-s <size> Size of buffer {default: 100KB}\n"
  221. "\t-h Print this help message\n",
  222. argv[0]);
  223. return -EINVAL;
  224. }
  225. return run_test(test);
  226. }