pci.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. #include "rte_config.h"
  2. /* SPDX-License-Identifier: BSD-3-Clause
  3. * Copyright(c) 2010-2014 Intel Corporation
  4. */
  5. #include <string.h>
  6. #include <dirent.h>
  7. #include <rte_log.h>
  8. #include <rte_bus.h>
  9. #include <rte_pci.h>
  10. #include <rte_bus_pci.h>
  11. #include <rte_malloc.h>
  12. #include <rte_devargs.h>
  13. #include <rte_memcpy.h>
  14. #include <rte_vfio.h>
  15. #include "eal_filesystem.h"
  16. #include "private.h"
  17. #include "pci_init.h"
  18. /**
  19. * @file
  20. * PCI probing under linux
  21. *
  22. * This code is used to simulate a PCI probe by parsing information in sysfs.
  23. * When a registered device matches a driver, it is then initialized with
  24. * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  25. */
  26. extern struct rte_pci_bus rte_pci_bus;
  27. static int
  28. pci_get_kernel_driver_by_path(const char *filename, char *dri_name,
  29. size_t len)
  30. {
  31. int count;
  32. char path[PATH_MAX];
  33. char *name;
  34. if (!filename || !dri_name)
  35. return -1;
  36. count = readlink(filename, path, PATH_MAX);
  37. if (count >= PATH_MAX)
  38. return -1;
  39. /* For device does not have a driver */
  40. if (count < 0)
  41. return 1;
  42. path[count] = '\0';
  43. name = strrchr(path, '/');
  44. if (name) {
  45. strlcpy(dri_name, name + 1, len);
  46. return 0;
  47. }
  48. return -1;
  49. }
  50. /* Map pci device */
  51. int
  52. rte_pci_map_device(struct rte_pci_device *dev)
  53. {
  54. int ret = -1;
  55. /* try mapping the NIC resources using VFIO if it exists */
  56. switch (dev->kdrv) {
  57. case RTE_PCI_KDRV_VFIO:
  58. #ifdef VFIO_PRESENT
  59. if (pci_vfio_is_enabled())
  60. ret = pci_vfio_map_resource(dev);
  61. #endif
  62. break;
  63. case RTE_PCI_KDRV_IGB_UIO:
  64. case RTE_PCI_KDRV_UIO_GENERIC:
  65. if (rte_eal_using_phys_addrs()) {
  66. /* map resources for devices that use uio */
  67. ret = pci_uio_map_resource(dev);
  68. }
  69. break;
  70. default:
  71. RTE_LOG(DEBUG, EAL,
  72. " Not managed by a supported kernel driver, skipped\n");
  73. ret = 1;
  74. break;
  75. }
  76. return ret;
  77. }
  78. /* Unmap pci device */
  79. void
  80. rte_pci_unmap_device(struct rte_pci_device *dev)
  81. {
  82. /* try unmapping the NIC resources using VFIO if it exists */
  83. switch (dev->kdrv) {
  84. case RTE_PCI_KDRV_VFIO:
  85. #ifdef VFIO_PRESENT
  86. if (pci_vfio_is_enabled())
  87. pci_vfio_unmap_resource(dev);
  88. #endif
  89. break;
  90. case RTE_PCI_KDRV_IGB_UIO:
  91. case RTE_PCI_KDRV_UIO_GENERIC:
  92. /* unmap resources for devices that use uio */
  93. pci_uio_unmap_resource(dev);
  94. break;
  95. default:
  96. RTE_LOG(DEBUG, EAL,
  97. " Not managed by a supported kernel driver, skipped\n");
  98. break;
  99. }
  100. }
  101. static int
  102. find_max_end_va(const struct rte_memseg_list *msl, void *arg)
  103. {
  104. size_t sz = msl->len;
  105. void *end_va = RTE_PTR_ADD(msl->base_va, sz);
  106. void **max_va = arg;
  107. if (*max_va < end_va)
  108. *max_va = end_va;
  109. return 0;
  110. }
  111. void *
  112. pci_find_max_end_va(void)
  113. {
  114. void *va = NULL;
  115. rte_memseg_list_walk(find_max_end_va, &va);
  116. return va;
  117. }
  118. /* parse one line of the "resource" sysfs file (note that the 'line'
  119. * string is modified)
  120. */
  121. int
  122. pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,
  123. uint64_t *end_addr, uint64_t *flags)
  124. {
  125. union pci_resource_info {
  126. struct {
  127. char *phys_addr;
  128. char *end_addr;
  129. char *flags;
  130. };
  131. char *ptrs[PCI_RESOURCE_FMT_NVAL];
  132. } res_info;
  133. if (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3) {
  134. RTE_LOG(ERR, EAL,
  135. "%s(): bad resource format\n", __func__);
  136. return -1;
  137. }
  138. errno = 0;
  139. *phys_addr = strtoull(res_info.phys_addr, NULL, 16);
  140. *end_addr = strtoull(res_info.end_addr, NULL, 16);
  141. *flags = strtoull(res_info.flags, NULL, 16);
  142. if (errno != 0) {
  143. RTE_LOG(ERR, EAL,
  144. "%s(): bad resource format\n", __func__);
  145. return -1;
  146. }
  147. return 0;
  148. }
  149. /* parse the "resource" sysfs file */
  150. static int
  151. pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
  152. {
  153. FILE *f;
  154. char buf[BUFSIZ];
  155. int i;
  156. uint64_t phys_addr, end_addr, flags;
  157. f = fopen(filename, "r");
  158. if (f == NULL) {
  159. RTE_LOG(ERR, EAL, "Cannot open sysfs resource\n");
  160. return -1;
  161. }
  162. for (i = 0; i<PCI_MAX_RESOURCE; i++) {
  163. if (fgets(buf, sizeof(buf), f) == NULL) {
  164. RTE_LOG(ERR, EAL,
  165. "%s(): cannot read resource\n", __func__);
  166. goto error;
  167. }
  168. if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
  169. &end_addr, &flags) < 0)
  170. goto error;
  171. if (flags & IORESOURCE_MEM) {
  172. dev->mem_resource[i].phys_addr = phys_addr;
  173. dev->mem_resource[i].len = end_addr - phys_addr + 1;
  174. /* not mapped for now */
  175. dev->mem_resource[i].addr = NULL;
  176. }
  177. }
  178. fclose(f);
  179. return 0;
  180. error:
  181. fclose(f);
  182. return -1;
  183. }
  184. /* Scan one pci sysfs entry, and fill the devices list from it. */
  185. static int
  186. pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
  187. {
  188. char filename[PATH_MAX];
  189. unsigned long tmp;
  190. struct rte_pci_device *dev;
  191. char driver[PATH_MAX];
  192. int ret;
  193. dev = malloc(sizeof(*dev));
  194. if (dev == NULL)
  195. return -1;
  196. memset(dev, 0, sizeof(*dev));
  197. dev->device.bus = &rte_pci_bus.bus;
  198. dev->addr = *addr;
  199. /* get vendor id */
  200. snprintf(filename, sizeof(filename), "%s/vendor", dirname);
  201. if (eal_parse_sysfs_value(filename, &tmp) < 0) {
  202. free(dev);
  203. return -1;
  204. }
  205. dev->id.vendor_id = (uint16_t)tmp;
  206. /* get device id */
  207. snprintf(filename, sizeof(filename), "%s/device", dirname);
  208. if (eal_parse_sysfs_value(filename, &tmp) < 0) {
  209. free(dev);
  210. return -1;
  211. }
  212. dev->id.device_id = (uint16_t)tmp;
  213. /* get subsystem_vendor id */
  214. snprintf(filename, sizeof(filename), "%s/subsystem_vendor",
  215. dirname);
  216. if (eal_parse_sysfs_value(filename, &tmp) < 0) {
  217. free(dev);
  218. return -1;
  219. }
  220. dev->id.subsystem_vendor_id = (uint16_t)tmp;
  221. /* get subsystem_device id */
  222. snprintf(filename, sizeof(filename), "%s/subsystem_device",
  223. dirname);
  224. if (eal_parse_sysfs_value(filename, &tmp) < 0) {
  225. free(dev);
  226. return -1;
  227. }
  228. dev->id.subsystem_device_id = (uint16_t)tmp;
  229. /* get class_id */
  230. snprintf(filename, sizeof(filename), "%s/class",
  231. dirname);
  232. if (eal_parse_sysfs_value(filename, &tmp) < 0) {
  233. free(dev);
  234. return -1;
  235. }
  236. /* the least 24 bits are valid: class, subclass, program interface */
  237. dev->id.class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID;
  238. /* get max_vfs */
  239. dev->max_vfs = 0;
  240. snprintf(filename, sizeof(filename), "%s/max_vfs", dirname);
  241. if (!access(filename, F_OK) &&
  242. eal_parse_sysfs_value(filename, &tmp) == 0)
  243. dev->max_vfs = (uint16_t)tmp;
  244. else {
  245. /* for non igb_uio driver, need kernel version >= 3.8 */
  246. snprintf(filename, sizeof(filename),
  247. "%s/sriov_numvfs", dirname);
  248. if (!access(filename, F_OK) &&
  249. eal_parse_sysfs_value(filename, &tmp) == 0)
  250. dev->max_vfs = (uint16_t)tmp;
  251. }
  252. /* get numa node, default to 0 if not present */
  253. snprintf(filename, sizeof(filename), "%s/numa_node",
  254. dirname);
  255. if (access(filename, F_OK) != -1) {
  256. if (eal_parse_sysfs_value(filename, &tmp) == 0)
  257. dev->device.numa_node = tmp;
  258. else
  259. dev->device.numa_node = -1;
  260. } else {
  261. dev->device.numa_node = 0;
  262. }
  263. pci_name_set(dev);
  264. /* parse resources */
  265. snprintf(filename, sizeof(filename), "%s/resource", dirname);
  266. if (pci_parse_sysfs_resource(filename, dev) < 0) {
  267. RTE_LOG(ERR, EAL, "%s(): cannot parse resource\n", __func__);
  268. free(dev);
  269. return -1;
  270. }
  271. /* parse driver */
  272. snprintf(filename, sizeof(filename), "%s/driver", dirname);
  273. ret = pci_get_kernel_driver_by_path(filename, driver, sizeof(driver));
  274. if (ret < 0) {
  275. RTE_LOG(ERR, EAL, "Fail to get kernel driver\n");
  276. free(dev);
  277. return -1;
  278. }
  279. if (!ret) {
  280. if (!strcmp(driver, "vfio-pci"))
  281. dev->kdrv = RTE_PCI_KDRV_VFIO;
  282. else if (!strcmp(driver, "igb_uio"))
  283. dev->kdrv = RTE_PCI_KDRV_IGB_UIO;
  284. else if (!strcmp(driver, "uio_pci_generic"))
  285. dev->kdrv = RTE_PCI_KDRV_UIO_GENERIC;
  286. else
  287. dev->kdrv = RTE_PCI_KDRV_UNKNOWN;
  288. } else {
  289. dev->kdrv = RTE_PCI_KDRV_NONE;
  290. return 0;
  291. }
  292. /* device is valid, add in list (sorted) */
  293. if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
  294. rte_pci_add_device(dev);
  295. } else {
  296. struct rte_pci_device *dev2;
  297. int ret;
  298. TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
  299. ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
  300. if (ret > 0)
  301. continue;
  302. if (ret < 0) {
  303. rte_pci_insert_device(dev2, dev);
  304. } else { /* already registered */
  305. if (!rte_dev_is_probed(&dev2->device)) {
  306. dev2->kdrv = dev->kdrv;
  307. dev2->max_vfs = dev->max_vfs;
  308. dev2->id = dev->id;
  309. pci_name_set(dev2);
  310. memmove(dev2->mem_resource,
  311. dev->mem_resource,
  312. sizeof(dev->mem_resource));
  313. } else {
  314. /**
  315. * If device is plugged and driver is
  316. * probed already, (This happens when
  317. * we call rte_dev_probe which will
  318. * scan all device on the bus) we don't
  319. * need to do anything here unless...
  320. **/
  321. if (dev2->kdrv != dev->kdrv ||
  322. dev2->max_vfs != dev->max_vfs ||
  323. memcmp(&dev2->id, &dev->id, sizeof(dev2->id)))
  324. /*
  325. * This should not happens.
  326. * But it is still possible if
  327. * we unbind a device from
  328. * vfio or uio before hotplug
  329. * remove and rebind it with
  330. * a different configure.
  331. * So we just print out the
  332. * error as an alarm.
  333. */
  334. RTE_LOG(ERR, EAL, "Unexpected device scan at %s!\n",
  335. filename);
  336. else if (dev2->device.devargs !=
  337. dev->device.devargs) {
  338. rte_devargs_remove(dev2->device.devargs);
  339. pci_name_set(dev2);
  340. }
  341. }
  342. free(dev);
  343. }
  344. return 0;
  345. }
  346. rte_pci_add_device(dev);
  347. }
  348. return 0;
  349. }
  350. /*
  351. * split up a pci address into its constituent parts.
  352. */
  353. static int
  354. parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
  355. {
  356. /* first split on ':' */
  357. union splitaddr {
  358. struct {
  359. char *domain;
  360. char *bus;
  361. char *devid;
  362. char *function;
  363. };
  364. char *str[PCI_FMT_NVAL]; /* last element-separator is "." not ":" */
  365. } splitaddr;
  366. char *buf_copy = strndup(buf, bufsize);
  367. if (buf_copy == NULL)
  368. return -1;
  369. if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')
  370. != PCI_FMT_NVAL - 1)
  371. goto error;
  372. /* final split is on '.' between devid and function */
  373. splitaddr.function = strchr(splitaddr.devid,'.');
  374. if (splitaddr.function == NULL)
  375. goto error;
  376. *splitaddr.function++ = '\0';
  377. /* now convert to int values */
  378. errno = 0;
  379. addr->domain = strtoul(splitaddr.domain, NULL, 16);
  380. addr->bus = strtoul(splitaddr.bus, NULL, 16);
  381. addr->devid = strtoul(splitaddr.devid, NULL, 16);
  382. addr->function = strtoul(splitaddr.function, NULL, 10);
  383. if (errno != 0)
  384. goto error;
  385. free(buf_copy); /* free the copy made with strdup */
  386. return 0;
  387. error:
  388. free(buf_copy);
  389. return -1;
  390. }
  391. /*
  392. * Scan the content of the PCI bus, and the devices in the devices
  393. * list
  394. */
  395. int
  396. rte_pci_scan(void)
  397. {
  398. struct dirent *e;
  399. DIR *dir;
  400. char dirname[PATH_MAX];
  401. struct rte_pci_addr addr;
  402. /* for debug purposes, PCI can be disabled */
  403. if (!rte_eal_has_pci())
  404. return 0;
  405. #ifdef VFIO_PRESENT
  406. if (!pci_vfio_is_enabled())
  407. RTE_LOG(DEBUG, EAL, "VFIO PCI modules not loaded\n");
  408. #endif
  409. dir = opendir(rte_pci_get_sysfs_path());
  410. if (dir == NULL) {
  411. RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
  412. __func__, strerror(errno));
  413. return -1;
  414. }
  415. while ((e = readdir(dir)) != NULL) {
  416. if (e->d_name[0] == '.')
  417. continue;
  418. if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &addr) != 0)
  419. continue;
  420. if (rte_pci_ignore_device(&addr))
  421. continue;
  422. snprintf(dirname, sizeof(dirname), "%s/%s",
  423. rte_pci_get_sysfs_path(), e->d_name);
  424. if (pci_scan_one(dirname, &addr) < 0)
  425. goto error;
  426. }
  427. closedir(dir);
  428. return 0;
  429. error:
  430. closedir(dir);
  431. return -1;
  432. }
  433. #if defined(RTE_ARCH_X86)
  434. bool
  435. pci_device_iommu_support_va(const struct rte_pci_device *dev)
  436. {
  437. #define VTD_CAP_MGAW_SHIFT 16
  438. #define VTD_CAP_MGAW_MASK (0x3fULL << VTD_CAP_MGAW_SHIFT)
  439. const struct rte_pci_addr *addr = &dev->addr;
  440. char filename[PATH_MAX];
  441. FILE *fp;
  442. uint64_t mgaw, vtd_cap_reg = 0;
  443. snprintf(filename, sizeof(filename),
  444. "%s/" PCI_PRI_FMT "/iommu/intel-iommu/cap",
  445. rte_pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
  446. addr->function);
  447. fp = fopen(filename, "r");
  448. if (fp == NULL) {
  449. /* We don't have an Intel IOMMU, assume VA supported */
  450. if (errno == ENOENT)
  451. return true;
  452. RTE_LOG(ERR, EAL, "%s(): can't open %s: %s\n",
  453. __func__, filename, strerror(errno));
  454. return false;
  455. }
  456. /* We have an Intel IOMMU */
  457. if (fscanf(fp, "%" PRIx64, &vtd_cap_reg) != 1) {
  458. RTE_LOG(ERR, EAL, "%s(): can't read %s\n", __func__, filename);
  459. fclose(fp);
  460. return false;
  461. }
  462. fclose(fp);
  463. mgaw = ((vtd_cap_reg & VTD_CAP_MGAW_MASK) >> VTD_CAP_MGAW_SHIFT) + 1;
  464. /*
  465. * Assuming there is no limitation by now. We can not know at this point
  466. * because the memory has not been initialized yet. Setting the dma mask
  467. * will force a check once memory initialization is done. We can not do
  468. * a fallback to IOVA PA now, but if the dma check fails, the error
  469. * message should advice for using '--iova-mode pa' if IOVA VA is the
  470. * current mode.
  471. */
  472. rte_mem_set_dma_mask(mgaw);
  473. return true;
  474. }
  475. #elif defined(RTE_ARCH_PPC_64)
  476. bool
  477. pci_device_iommu_support_va(__rte_unused const struct rte_pci_device *dev)
  478. {
  479. /*
  480. * IOMMU is always present on a PowerNV host (IOMMUv2).
  481. * IOMMU is also present in a KVM/QEMU VM (IOMMUv1) but is not
  482. * currently supported by DPDK. Test for our current environment
  483. * and report VA support as appropriate.
  484. */
  485. char *line = NULL;
  486. size_t len = 0;
  487. char filename[PATH_MAX] = "/proc/cpuinfo";
  488. FILE *fp = fopen(filename, "r");
  489. bool ret = false;
  490. if (fp == NULL) {
  491. RTE_LOG(ERR, EAL, "%s(): can't open %s: %s\n",
  492. __func__, filename, strerror(errno));
  493. return ret;
  494. }
  495. /* Check for a PowerNV platform */
  496. while (getline(&line, &len, fp) != -1) {
  497. if (strstr(line, "platform") != NULL)
  498. continue;
  499. if (strstr(line, "PowerNV") != NULL) {
  500. RTE_LOG(DEBUG, EAL, "Running on a PowerNV system\n");
  501. ret = true;
  502. break;
  503. }
  504. }
  505. free(line);
  506. fclose(fp);
  507. return ret;
  508. }
  509. #else
  510. bool
  511. pci_device_iommu_support_va(__rte_unused const struct rte_pci_device *dev)
  512. {
  513. return true;
  514. }
  515. #endif
  516. enum rte_iova_mode
  517. pci_device_iova_mode(const struct rte_pci_driver *pdrv,
  518. const struct rte_pci_device *pdev)
  519. {
  520. enum rte_iova_mode iova_mode = RTE_IOVA_DC;
  521. switch (pdev->kdrv) {
  522. case RTE_PCI_KDRV_VFIO: {
  523. #ifdef VFIO_PRESENT
  524. static int is_vfio_noiommu_enabled = -1;
  525. if (is_vfio_noiommu_enabled == -1) {
  526. if (rte_vfio_noiommu_is_enabled() == 1)
  527. is_vfio_noiommu_enabled = 1;
  528. else
  529. is_vfio_noiommu_enabled = 0;
  530. }
  531. if (is_vfio_noiommu_enabled != 0)
  532. iova_mode = RTE_IOVA_PA;
  533. else if ((pdrv->drv_flags & RTE_PCI_DRV_NEED_IOVA_AS_VA) != 0)
  534. iova_mode = RTE_IOVA_VA;
  535. #endif
  536. break;
  537. }
  538. case RTE_PCI_KDRV_IGB_UIO:
  539. case RTE_PCI_KDRV_UIO_GENERIC:
  540. iova_mode = RTE_IOVA_PA;
  541. break;
  542. default:
  543. if ((pdrv->drv_flags & RTE_PCI_DRV_NEED_IOVA_AS_VA) != 0)
  544. iova_mode = RTE_IOVA_VA;
  545. break;
  546. }
  547. return iova_mode;
  548. }
  549. /* Read PCI config space. */
  550. int rte_pci_read_config(const struct rte_pci_device *device,
  551. void *buf, size_t len, off_t offset)
  552. {
  553. char devname[RTE_DEV_NAME_MAX_LEN] = "";
  554. const struct rte_intr_handle *intr_handle = &device->intr_handle;
  555. switch (device->kdrv) {
  556. case RTE_PCI_KDRV_IGB_UIO:
  557. case RTE_PCI_KDRV_UIO_GENERIC:
  558. return pci_uio_read_config(intr_handle, buf, len, offset);
  559. #ifdef VFIO_PRESENT
  560. case RTE_PCI_KDRV_VFIO:
  561. return pci_vfio_read_config(intr_handle, buf, len, offset);
  562. #endif
  563. default:
  564. rte_pci_device_name(&device->addr, devname,
  565. RTE_DEV_NAME_MAX_LEN);
  566. RTE_LOG(ERR, EAL,
  567. "Unknown driver type for %s\n", devname);
  568. return -1;
  569. }
  570. }
  571. /* Write PCI config space. */
  572. int rte_pci_write_config(const struct rte_pci_device *device,
  573. const void *buf, size_t len, off_t offset)
  574. {
  575. char devname[RTE_DEV_NAME_MAX_LEN] = "";
  576. const struct rte_intr_handle *intr_handle = &device->intr_handle;
  577. switch (device->kdrv) {
  578. case RTE_PCI_KDRV_IGB_UIO:
  579. case RTE_PCI_KDRV_UIO_GENERIC:
  580. return pci_uio_write_config(intr_handle, buf, len, offset);
  581. #ifdef VFIO_PRESENT
  582. case RTE_PCI_KDRV_VFIO:
  583. return pci_vfio_write_config(intr_handle, buf, len, offset);
  584. #endif
  585. default:
  586. rte_pci_device_name(&device->addr, devname,
  587. RTE_DEV_NAME_MAX_LEN);
  588. RTE_LOG(ERR, EAL,
  589. "Unknown driver type for %s\n", devname);
  590. return -1;
  591. }
  592. }
  593. #if defined(RTE_ARCH_X86)
  594. static int
  595. pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused,
  596. struct rte_pci_ioport *p)
  597. {
  598. uint16_t start, end;
  599. FILE *fp;
  600. char *line = NULL;
  601. char pci_id[16];
  602. int found = 0;
  603. size_t linesz;
  604. if (rte_eal_iopl_init() != 0) {
  605. RTE_LOG(ERR, EAL, "%s(): insufficient ioport permissions for PCI device %s\n",
  606. __func__, dev->name);
  607. return -1;
  608. }
  609. snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT,
  610. dev->addr.domain, dev->addr.bus,
  611. dev->addr.devid, dev->addr.function);
  612. fp = fopen("/proc/ioports", "r");
  613. if (fp == NULL) {
  614. RTE_LOG(ERR, EAL, "%s(): can't open ioports\n", __func__);
  615. return -1;
  616. }
  617. while (getdelim(&line, &linesz, '\n', fp) > 0) {
  618. char *ptr = line;
  619. char *left;
  620. int n;
  621. n = strcspn(ptr, ":");
  622. ptr[n] = 0;
  623. left = &ptr[n + 1];
  624. while (*left && isspace(*left))
  625. left++;
  626. if (!strncmp(left, pci_id, strlen(pci_id))) {
  627. found = 1;
  628. while (*ptr && isspace(*ptr))
  629. ptr++;
  630. sscanf(ptr, "%04hx-%04hx", &start, &end);
  631. break;
  632. }
  633. }
  634. free(line);
  635. fclose(fp);
  636. if (!found)
  637. return -1;
  638. p->base = start;
  639. RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%x\n", start);
  640. return 0;
  641. }
  642. #endif
  643. int
  644. rte_pci_ioport_map(struct rte_pci_device *dev, int bar,
  645. struct rte_pci_ioport *p)
  646. {
  647. int ret = -1;
  648. switch (dev->kdrv) {
  649. #ifdef VFIO_PRESENT
  650. case RTE_PCI_KDRV_VFIO:
  651. if (pci_vfio_is_enabled())
  652. ret = pci_vfio_ioport_map(dev, bar, p);
  653. break;
  654. #endif
  655. case RTE_PCI_KDRV_IGB_UIO:
  656. ret = pci_uio_ioport_map(dev, bar, p);
  657. break;
  658. case RTE_PCI_KDRV_UIO_GENERIC:
  659. #if defined(RTE_ARCH_X86)
  660. ret = pci_ioport_map(dev, bar, p);
  661. #else
  662. ret = pci_uio_ioport_map(dev, bar, p);
  663. #endif
  664. break;
  665. default:
  666. break;
  667. }
  668. if (!ret)
  669. p->dev = dev;
  670. return ret;
  671. }
  672. void
  673. rte_pci_ioport_read(struct rte_pci_ioport *p,
  674. void *data, size_t len, off_t offset)
  675. {
  676. switch (p->dev->kdrv) {
  677. #ifdef VFIO_PRESENT
  678. case RTE_PCI_KDRV_VFIO:
  679. pci_vfio_ioport_read(p, data, len, offset);
  680. break;
  681. #endif
  682. case RTE_PCI_KDRV_IGB_UIO:
  683. pci_uio_ioport_read(p, data, len, offset);
  684. break;
  685. case RTE_PCI_KDRV_UIO_GENERIC:
  686. pci_uio_ioport_read(p, data, len, offset);
  687. break;
  688. default:
  689. break;
  690. }
  691. }
  692. void
  693. rte_pci_ioport_write(struct rte_pci_ioport *p,
  694. const void *data, size_t len, off_t offset)
  695. {
  696. switch (p->dev->kdrv) {
  697. #ifdef VFIO_PRESENT
  698. case RTE_PCI_KDRV_VFIO:
  699. pci_vfio_ioport_write(p, data, len, offset);
  700. break;
  701. #endif
  702. case RTE_PCI_KDRV_IGB_UIO:
  703. pci_uio_ioport_write(p, data, len, offset);
  704. break;
  705. case RTE_PCI_KDRV_UIO_GENERIC:
  706. pci_uio_ioport_write(p, data, len, offset);
  707. break;
  708. default:
  709. break;
  710. }
  711. }
  712. int
  713. rte_pci_ioport_unmap(struct rte_pci_ioport *p)
  714. {
  715. int ret = -1;
  716. switch (p->dev->kdrv) {
  717. #ifdef VFIO_PRESENT
  718. case RTE_PCI_KDRV_VFIO:
  719. if (pci_vfio_is_enabled())
  720. ret = pci_vfio_ioport_unmap(p);
  721. break;
  722. #endif
  723. case RTE_PCI_KDRV_IGB_UIO:
  724. ret = pci_uio_ioport_unmap(p);
  725. break;
  726. case RTE_PCI_KDRV_UIO_GENERIC:
  727. #if defined(RTE_ARCH_X86)
  728. ret = 0;
  729. #else
  730. ret = pci_uio_ioport_unmap(p);
  731. #endif
  732. break;
  733. default:
  734. break;
  735. }
  736. return ret;
  737. }