net/virtio: fix incorrect cast of void *
[dpdk.git] / linux / pci_uio.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <string.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <dirent.h>
9 #include <inttypes.h>
10 #include <sys/stat.h>
11 #include <sys/mman.h>
12 #include <sys/sysmacros.h>
13 #include <linux/pci_regs.h>
14
15 #if defined(RTE_ARCH_X86)
16 #include <sys/io.h>
17 #endif
18
19 #include <rte_string_fns.h>
20 #include <rte_log.h>
21 #include <rte_pci.h>
22 #include <rte_bus_pci.h>
23 #include <rte_common.h>
24 #include <rte_malloc.h>
25
26 #include "eal_filesystem.h"
27 #include "pci_init.h"
28 #include "private.h"
29
30 void *pci_map_addr = NULL;
31
32 #define OFF_MAX              ((uint64_t)(off_t)-1)
33
34 int
35 pci_uio_read_config(const struct rte_intr_handle *intr_handle,
36                     void *buf, size_t len, off_t offset)
37 {
38         int uio_cfg_fd = rte_intr_dev_fd_get(intr_handle);
39
40         if (uio_cfg_fd < 0)
41                 return -1;
42
43         return pread(uio_cfg_fd, buf, len, offset);
44 }
45
46 int
47 pci_uio_write_config(const struct rte_intr_handle *intr_handle,
48                      const void *buf, size_t len, off_t offset)
49 {
50         int uio_cfg_fd = rte_intr_dev_fd_get(intr_handle);
51
52         if (uio_cfg_fd < 0)
53                 return -1;
54
55         return pwrite(uio_cfg_fd, buf, len, offset);
56 }
57
58 static int
59 pci_uio_set_bus_master(int dev_fd)
60 {
61         uint16_t reg;
62         int ret;
63
64         ret = pread(dev_fd, &reg, sizeof(reg), PCI_COMMAND);
65         if (ret != sizeof(reg)) {
66                 RTE_LOG(ERR, EAL,
67                         "Cannot read command from PCI config space!\n");
68                 return -1;
69         }
70
71         /* return if bus mastering is already on */
72         if (reg & PCI_COMMAND_MASTER)
73                 return 0;
74
75         reg |= PCI_COMMAND_MASTER;
76
77         ret = pwrite(dev_fd, &reg, sizeof(reg), PCI_COMMAND);
78         if (ret != sizeof(reg)) {
79                 RTE_LOG(ERR, EAL,
80                         "Cannot write command to PCI config space!\n");
81                 return -1;
82         }
83
84         return 0;
85 }
86
87 static int
88 pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num)
89 {
90         FILE *f;
91         char filename[PATH_MAX];
92         int ret;
93         unsigned major, minor;
94         dev_t dev;
95
96         /* get the name of the sysfs file that contains the major and minor
97          * of the uio device and read its content */
98         snprintf(filename, sizeof(filename), "%s/dev", sysfs_uio_path);
99
100         f = fopen(filename, "r");
101         if (f == NULL) {
102                 RTE_LOG(ERR, EAL, "%s(): cannot open sysfs to get major:minor\n",
103                         __func__);
104                 return -1;
105         }
106
107         ret = fscanf(f, "%u:%u", &major, &minor);
108         if (ret != 2) {
109                 RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs to get major:minor\n",
110                         __func__);
111                 fclose(f);
112                 return -1;
113         }
114         fclose(f);
115
116         /* create the char device "mknod /dev/uioX c major minor" */
117         snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num);
118         dev = makedev(major, minor);
119         ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev);
120         if (ret != 0) {
121                 RTE_LOG(ERR, EAL, "%s(): mknod() failed %s\n",
122                         __func__, strerror(errno));
123                 return -1;
124         }
125
126         return ret;
127 }
128
129 /*
130  * Return the uioX char device used for a pci device. On success, return
131  * the UIO number and fill dstbuf string with the path of the device in
132  * sysfs. On error, return a negative value. In this case dstbuf is
133  * invalid.
134  */
135 static int
136 pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf,
137                            unsigned int buflen, int create)
138 {
139         struct rte_pci_addr *loc = &dev->addr;
140         int uio_num = -1;
141         struct dirent *e;
142         DIR *dir;
143         char dirname[PATH_MAX];
144
145         /* depending on kernel version, uio can be located in uio/uioX
146          * or uio:uioX */
147
148         snprintf(dirname, sizeof(dirname),
149                         "%s/" PCI_PRI_FMT "/uio", rte_pci_get_sysfs_path(),
150                         loc->domain, loc->bus, loc->devid, loc->function);
151
152         dir = opendir(dirname);
153         if (dir == NULL) {
154                 /* retry with the parent directory */
155                 snprintf(dirname, sizeof(dirname),
156                                 "%s/" PCI_PRI_FMT, rte_pci_get_sysfs_path(),
157                                 loc->domain, loc->bus, loc->devid, loc->function);
158                 dir = opendir(dirname);
159
160                 if (dir == NULL) {
161                         RTE_LOG(ERR, EAL, "Cannot opendir %s\n", dirname);
162                         return -1;
163                 }
164         }
165
166         /* take the first file starting with "uio" */
167         while ((e = readdir(dir)) != NULL) {
168                 /* format could be uio%d ...*/
169                 int shortprefix_len = sizeof("uio") - 1;
170                 /* ... or uio:uio%d */
171                 int longprefix_len = sizeof("uio:uio") - 1;
172                 char *endptr;
173
174                 if (strncmp(e->d_name, "uio", 3) != 0)
175                         continue;
176
177                 /* first try uio%d */
178                 errno = 0;
179                 uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);
180                 if (errno == 0 && endptr != (e->d_name + shortprefix_len)) {
181                         snprintf(dstbuf, buflen, "%s/uio%u", dirname, uio_num);
182                         break;
183                 }
184
185                 /* then try uio:uio%d */
186                 errno = 0;
187                 uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);
188                 if (errno == 0 && endptr != (e->d_name + longprefix_len)) {
189                         snprintf(dstbuf, buflen, "%s/uio:uio%u", dirname, uio_num);
190                         break;
191                 }
192         }
193         closedir(dir);
194
195         /* No uio resource found */
196         if (e == NULL)
197                 return -1;
198
199         /* create uio device if we've been asked to */
200         if (rte_eal_create_uio_dev() && create &&
201                         pci_mknod_uio_dev(dstbuf, uio_num) < 0)
202                 RTE_LOG(WARNING, EAL, "Cannot create /dev/uio%u\n", uio_num);
203
204         return uio_num;
205 }
206
207 void
208 pci_uio_free_resource(struct rte_pci_device *dev,
209                 struct mapped_pci_resource *uio_res)
210 {
211         int uio_cfg_fd = rte_intr_dev_fd_get(dev->intr_handle);
212
213         rte_free(uio_res);
214
215         if (uio_cfg_fd >= 0) {
216                 close(uio_cfg_fd);
217                 rte_intr_dev_fd_set(dev->intr_handle, -1);
218         }
219
220         if (rte_intr_fd_get(dev->intr_handle) >= 0) {
221                 close(rte_intr_fd_get(dev->intr_handle));
222                 rte_intr_fd_set(dev->intr_handle, -1);
223                 rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
224         }
225 }
226
227 int
228 pci_uio_alloc_resource(struct rte_pci_device *dev,
229                 struct mapped_pci_resource **uio_res)
230 {
231         char dirname[PATH_MAX];
232         char cfgname[PATH_MAX];
233         char devname[PATH_MAX]; /* contains the /dev/uioX */
234         int uio_num, fd, uio_cfg_fd;
235         struct rte_pci_addr *loc;
236
237         loc = &dev->addr;
238
239         /* find uio resource */
240         uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 1);
241         if (uio_num < 0) {
242                 RTE_LOG(WARNING, EAL, "  "PCI_PRI_FMT" not managed by UIO driver, "
243                                 "skipping\n", loc->domain, loc->bus, loc->devid, loc->function);
244                 return 1;
245         }
246         snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num);
247
248         /* save fd if in primary process */
249         fd = open(devname, O_RDWR);
250         if (fd < 0) {
251                 RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
252                         devname, strerror(errno));
253                 goto error;
254         }
255
256         if (rte_intr_fd_set(dev->intr_handle, fd))
257                 goto error;
258
259         snprintf(cfgname, sizeof(cfgname),
260                         "/sys/class/uio/uio%u/device/config", uio_num);
261
262         uio_cfg_fd = open(cfgname, O_RDWR);
263         if (uio_cfg_fd < 0) {
264                 RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
265                         cfgname, strerror(errno));
266                 goto error;
267         }
268
269         if (rte_intr_dev_fd_set(dev->intr_handle, uio_cfg_fd))
270                 goto error;
271
272         if (dev->kdrv == RTE_PCI_KDRV_IGB_UIO) {
273                 if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO))
274                         goto error;
275         } else {
276                 if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO_INTX))
277                         goto error;
278
279                 /* set bus master that is not done by uio_pci_generic */
280                 if (pci_uio_set_bus_master(uio_cfg_fd)) {
281                         RTE_LOG(ERR, EAL, "Cannot set up bus mastering!\n");
282                         goto error;
283                 }
284         }
285
286         /* allocate the mapping details for secondary processes*/
287         *uio_res = rte_zmalloc("UIO_RES", sizeof(**uio_res), 0);
288         if (*uio_res == NULL) {
289                 RTE_LOG(ERR, EAL,
290                         "%s(): cannot store uio mmap details\n", __func__);
291                 goto error;
292         }
293
294         strlcpy((*uio_res)->path, devname, sizeof((*uio_res)->path));
295         memcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr));
296
297         return 0;
298
299 error:
300         pci_uio_free_resource(dev, *uio_res);
301         return -1;
302 }
303
304 int
305 pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
306                 struct mapped_pci_resource *uio_res, int map_idx)
307 {
308         int fd = -1;
309         char devname[PATH_MAX];
310         void *mapaddr;
311         struct rte_pci_addr *loc;
312         struct pci_map *maps;
313         int wc_activate = 0;
314
315         if (dev->driver != NULL)
316                 wc_activate = dev->driver->drv_flags & RTE_PCI_DRV_WC_ACTIVATE;
317
318         loc = &dev->addr;
319         maps = uio_res->maps;
320
321         /* allocate memory to keep path */
322         maps[map_idx].path = rte_malloc(NULL, sizeof(devname), 0);
323         if (maps[map_idx].path == NULL) {
324                 RTE_LOG(ERR, EAL, "Cannot allocate memory for path: %s\n",
325                                 strerror(errno));
326                 return -1;
327         }
328
329         /*
330          * open resource file, to mmap it
331          */
332         if (wc_activate) {
333                 /* update devname for mmap  */
334                 snprintf(devname, sizeof(devname),
335                         "%s/" PCI_PRI_FMT "/resource%d_wc",
336                         rte_pci_get_sysfs_path(),
337                         loc->domain, loc->bus, loc->devid,
338                         loc->function, res_idx);
339
340                 fd = open(devname, O_RDWR);
341                 if (fd < 0 && errno != ENOENT) {
342                         RTE_LOG(INFO, EAL, "%s cannot be mapped. "
343                                 "Fall-back to non prefetchable mode.\n",
344                                 devname);
345                 }
346         }
347
348         if (!wc_activate || fd < 0) {
349                 snprintf(devname, sizeof(devname),
350                         "%s/" PCI_PRI_FMT "/resource%d",
351                         rte_pci_get_sysfs_path(),
352                         loc->domain, loc->bus, loc->devid,
353                         loc->function, res_idx);
354
355                 /* then try to map resource file */
356                 fd = open(devname, O_RDWR);
357                 if (fd < 0) {
358                         RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
359                                 devname, strerror(errno));
360                         goto error;
361                 }
362         }
363
364         /* try mapping somewhere close to the end of hugepages */
365         if (pci_map_addr == NULL)
366                 pci_map_addr = pci_find_max_end_va();
367
368         mapaddr = pci_map_resource(pci_map_addr, fd, 0,
369                         (size_t)dev->mem_resource[res_idx].len, 0);
370         close(fd);
371         if (mapaddr == NULL)
372                 goto error;
373
374         pci_map_addr = RTE_PTR_ADD(mapaddr,
375                         (size_t)dev->mem_resource[res_idx].len);
376
377         pci_map_addr = RTE_PTR_ALIGN(pci_map_addr, sysconf(_SC_PAGE_SIZE));
378
379         maps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr;
380         maps[map_idx].size = dev->mem_resource[res_idx].len;
381         maps[map_idx].addr = mapaddr;
382         maps[map_idx].offset = 0;
383         strcpy(maps[map_idx].path, devname);
384         dev->mem_resource[res_idx].addr = mapaddr;
385
386         return 0;
387
388 error:
389         rte_free(maps[map_idx].path);
390         return -1;
391 }
392
393 #define PIO_MAX 0x10000
394
395 #if defined(RTE_ARCH_X86)
396 int
397 pci_uio_ioport_map(struct rte_pci_device *dev, int bar,
398                    struct rte_pci_ioport *p)
399 {
400         FILE *f = NULL;
401         char dirname[PATH_MAX];
402         char filename[PATH_MAX];
403         char buf[BUFSIZ];
404         uint64_t phys_addr, end_addr, flags;
405         unsigned long base;
406         int i, fd;
407
408         /* open and read addresses of the corresponding resource in sysfs */
409         snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource",
410                 rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
411                 dev->addr.devid, dev->addr.function);
412         f = fopen(filename, "r");
413         if (f == NULL) {
414                 RTE_LOG(ERR, EAL, "%s(): Cannot open sysfs resource: %s\n",
415                         __func__, strerror(errno));
416                 return -1;
417         }
418
419         for (i = 0; i < bar + 1; i++) {
420                 if (fgets(buf, sizeof(buf), f) == NULL) {
421                         RTE_LOG(ERR, EAL, "%s(): Cannot read sysfs resource\n", __func__);
422                         goto error;
423                 }
424         }
425         if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
426                 &end_addr, &flags) < 0)
427                 goto error;
428
429         if (flags & IORESOURCE_IO) {
430                 if (rte_eal_iopl_init()) {
431                         RTE_LOG(ERR, EAL, "%s(): insufficient ioport permissions for PCI device %s\n",
432                                 __func__, dev->name);
433                         goto error;
434                 }
435
436                 base = (unsigned long)phys_addr;
437                 if (base > PIO_MAX) {
438                         RTE_LOG(ERR, EAL, "%s(): %08lx too large PIO resource\n", __func__, base);
439                         goto error;
440                 }
441
442                 RTE_LOG(DEBUG, EAL, "%s(): PIO BAR %08lx detected\n", __func__, base);
443         } else if (flags & IORESOURCE_MEM) {
444                 base = (unsigned long)dev->mem_resource[bar].addr;
445                 RTE_LOG(DEBUG, EAL, "%s(): MMIO BAR %08lx detected\n", __func__, base);
446         } else {
447                 RTE_LOG(ERR, EAL, "%s(): unknown BAR type\n", __func__);
448                 goto error;
449         }
450
451         /* FIXME only for primary process ? */
452         if (rte_intr_type_get(dev->intr_handle) ==
453                                         RTE_INTR_HANDLE_UNKNOWN) {
454                 int uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 0);
455                 if (uio_num < 0) {
456                         RTE_LOG(ERR, EAL, "cannot open %s: %s\n",
457                                 dirname, strerror(errno));
458                         goto error;
459                 }
460
461                 snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num);
462                 fd = open(filename, O_RDWR);
463                 if (fd < 0) {
464                         RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
465                                 filename, strerror(errno));
466                         goto error;
467                 }
468                 if (rte_intr_fd_set(dev->intr_handle, fd))
469                         goto error;
470
471                 if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO))
472                         goto error;
473         }
474
475         RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%lx\n", base);
476
477         p->base = base;
478         p->len = 0;
479         fclose(f);
480         return 0;
481 error:
482         if (f)
483                 fclose(f);
484         return -1;
485 }
486 #else
487 int
488 pci_uio_ioport_map(struct rte_pci_device *dev, int bar,
489                    struct rte_pci_ioport *p)
490 {
491         FILE *f;
492         char buf[BUFSIZ];
493         char filename[PATH_MAX];
494         uint64_t phys_addr, end_addr, flags;
495         int fd, i;
496         void *addr;
497
498         /* open and read addresses of the corresponding resource in sysfs */
499         snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource",
500                 rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
501                 dev->addr.devid, dev->addr.function);
502         f = fopen(filename, "r");
503         if (f == NULL) {
504                 RTE_LOG(ERR, EAL, "Cannot open sysfs resource: %s\n",
505                         strerror(errno));
506                 return -1;
507         }
508         for (i = 0; i < bar + 1; i++) {
509                 if (fgets(buf, sizeof(buf), f) == NULL) {
510                         RTE_LOG(ERR, EAL, "Cannot read sysfs resource\n");
511                         goto error;
512                 }
513         }
514         if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
515                         &end_addr, &flags) < 0)
516                 goto error;
517         if ((flags & IORESOURCE_IO) == 0) {
518                 RTE_LOG(ERR, EAL, "BAR %d is not an IO resource\n", bar);
519                 goto error;
520         }
521         snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource%d",
522                 rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
523                 dev->addr.devid, dev->addr.function, bar);
524
525         /* mmap the pci resource */
526         fd = open(filename, O_RDWR);
527         if (fd < 0) {
528                 RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", filename,
529                         strerror(errno));
530                 goto error;
531         }
532         addr = mmap(NULL, end_addr + 1, PROT_READ | PROT_WRITE,
533                 MAP_SHARED, fd, 0);
534         close(fd);
535         if (addr == MAP_FAILED) {
536                 RTE_LOG(ERR, EAL, "Cannot mmap IO port resource: %s\n",
537                         strerror(errno));
538                 goto error;
539         }
540
541         /* strangely, the base address is mmap addr + phys_addr */
542         p->base = (uintptr_t)addr + phys_addr;
543         p->len = end_addr + 1;
544         RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%"PRIx64"\n", p->base);
545         fclose(f);
546
547         return 0;
548
549 error:
550         fclose(f);
551         return -1;
552 }
553 #endif
554
555 #if defined(RTE_ARCH_X86)
556
557 static inline uint8_t ioread8(void *addr)
558 {
559         uint8_t val;
560
561         val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
562                 *(volatile uint8_t *)addr :
563 #ifdef __GLIBC__
564                 inb_p((unsigned long)addr);
565 #else
566                 inb((unsigned long)addr);
567 #endif
568
569         return val;
570 }
571
572 static inline uint16_t ioread16(void *addr)
573 {
574         uint16_t val;
575
576         val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
577                 *(volatile uint16_t *)addr :
578 #ifdef __GLIBC__
579                 inw_p((unsigned long)addr);
580 #else
581                 inw((unsigned long)addr);
582 #endif
583
584         return val;
585 }
586
587 static inline uint32_t ioread32(void *addr)
588 {
589         uint32_t val;
590
591         val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
592                 *(volatile uint32_t *)addr :
593 #ifdef __GLIBC__
594                 inl_p((unsigned long)addr);
595 #else
596                 inl((unsigned long)addr);
597 #endif
598
599         return val;
600 }
601
602 static inline void iowrite8(uint8_t val, void *addr)
603 {
604         (uint64_t)(uintptr_t)addr >= PIO_MAX ?
605                 *(volatile uint8_t *)addr = val :
606 #ifdef __GLIBC__
607                 outb_p(val, (unsigned long)addr);
608 #else
609                 outb(val, (unsigned long)addr);
610 #endif
611 }
612
613 static inline void iowrite16(uint16_t val, void *addr)
614 {
615         (uint64_t)(uintptr_t)addr >= PIO_MAX ?
616                 *(volatile uint16_t *)addr = val :
617 #ifdef __GLIBC__
618                 outw_p(val, (unsigned long)addr);
619 #else
620                 outw(val, (unsigned long)addr);
621 #endif
622 }
623
624 static inline void iowrite32(uint32_t val, void *addr)
625 {
626         (uint64_t)(uintptr_t)addr >= PIO_MAX ?
627                 *(volatile uint32_t *)addr = val :
628 #ifdef __GLIBC__
629                 outl_p(val, (unsigned long)addr);
630 #else
631                 outl(val, (unsigned long)addr);
632 #endif
633 }
634
635 #else /* !RTE_ARCH_X86 */
636
637 static inline uint8_t ioread8(void *addr)
638 {
639         return *(volatile uint8_t *)addr;
640 }
641
642 static inline uint16_t ioread16(void *addr)
643 {
644         return *(volatile uint16_t *)addr;
645 }
646
647 static inline uint32_t ioread32(void *addr)
648 {
649         return *(volatile uint32_t *)addr;
650 }
651
652 static inline void iowrite8(uint8_t val, void *addr)
653 {
654         *(volatile uint8_t *)addr = val;
655 }
656
657 static inline void iowrite16(uint16_t val, void *addr)
658 {
659         *(volatile uint16_t *)addr = val;
660 }
661
662 static inline void iowrite32(uint32_t val, void *addr)
663 {
664         *(volatile uint32_t *)addr = val;
665 }
666
667 #endif /* !RTE_ARCH_X86 */
668
669 void
670 pci_uio_ioport_read(struct rte_pci_ioport *p,
671                     void *data, size_t len, off_t offset)
672 {
673         uint8_t *d;
674         int size;
675         uintptr_t reg = p->base + offset;
676
677         for (d = data; len > 0; d += size, reg += size, len -= size) {
678                 if (len >= 4) {
679                         size = 4;
680                         *(uint32_t *)d = ioread32((void *)reg);
681                 } else if (len >= 2) {
682                         size = 2;
683                         *(uint16_t *)d = ioread16((void *)reg);
684                 } else {
685                         size = 1;
686                         *d = ioread8((void *)reg);
687                 }
688         }
689 }
690
691 void
692 pci_uio_ioport_write(struct rte_pci_ioport *p,
693                      const void *data, size_t len, off_t offset)
694 {
695         const uint8_t *s;
696         int size;
697         uintptr_t reg = p->base + offset;
698
699         for (s = data; len > 0; s += size, reg += size, len -= size) {
700                 if (len >= 4) {
701                         size = 4;
702                         iowrite32(*(const uint32_t *)s, (void *)reg);
703                 } else if (len >= 2) {
704                         size = 2;
705                         iowrite16(*(const uint16_t *)s, (void *)reg);
706                 } else {
707                         size = 1;
708                         iowrite8(*s, (void *)reg);
709                 }
710         }
711 }
712
713 int
714 pci_uio_ioport_unmap(struct rte_pci_ioport *p)
715 {
716 #if defined(RTE_ARCH_X86)
717         RTE_SET_USED(p);
718         /* FIXME close intr fd ? */
719         return 0;
720 #else
721         return munmap((void *)(uintptr_t)p->base, p->len);
722 #endif
723 }