1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2015 Intel Corporation 3 */ 4 5 #include <fcntl.h> 6 #include <string.h> 7 #include <unistd.h> 8 #include <sys/types.h> 9 #include <sys/stat.h> 10 #include <sys/mman.h> 11 12 #include <rte_eal.h> 13 #include <rte_pci.h> 14 #include <rte_bus_pci.h> 15 #include <rte_tailq.h> 16 #include <rte_log.h> 17 #include <rte_malloc.h> 18 19 #include "private.h" 20 21 static struct rte_tailq_elem rte_uio_tailq = { 22 .name = "UIO_RESOURCE_LIST", 23 }; 24 EAL_REGISTER_TAILQ(rte_uio_tailq) 25 26 static int 27 pci_uio_map_secondary(struct rte_pci_device *dev) 28 { 29 int fd, i, j; 30 struct mapped_pci_resource *uio_res; 31 struct mapped_pci_res_list *uio_res_list = 32 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 33 34 TAILQ_FOREACH(uio_res, uio_res_list, next) { 35 36 /* skip this element if it doesn't match our PCI address */ 37 if (rte_pci_addr_cmp(&uio_res->pci_addr, &dev->addr)) 38 continue; 39 40 for (i = 0; i != uio_res->nb_maps; i++) { 41 /* 42 * open devname, to mmap it 43 */ 44 fd = open(uio_res->maps[i].path, O_RDWR); 45 if (fd < 0) { 46 RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", 47 uio_res->maps[i].path, strerror(errno)); 48 return -1; 49 } 50 51 void *mapaddr = pci_map_resource(uio_res->maps[i].addr, 52 fd, (off_t)uio_res->maps[i].offset, 53 (size_t)uio_res->maps[i].size, 0); 54 /* fd is not needed in slave process, close it */ 55 close(fd); 56 if (mapaddr != uio_res->maps[i].addr) { 57 RTE_LOG(ERR, EAL, 58 "Cannot mmap device resource file %s to address: %p\n", 59 uio_res->maps[i].path, 60 uio_res->maps[i].addr); 61 if (mapaddr != MAP_FAILED) { 62 /* unmap addrs correctly mapped */ 63 for (j = 0; j < i; j++) 64 pci_unmap_resource( 65 uio_res->maps[j].addr, 66 (size_t)uio_res->maps[j].size); 67 /* unmap addr wrongly mapped */ 68 pci_unmap_resource(mapaddr, 69 (size_t)uio_res->maps[i].size); 70 } 71 return -1; 72 } 73 } 74 return 0; 75 } 76 77 RTE_LOG(ERR, EAL, "Cannot find resource for device\n"); 78 return 1; 79 } 80 81 /* map the PCI resource of a PCI device in virtual memory */ 82 int 83 pci_uio_map_resource(struct rte_pci_device *dev) 84 { 85 int i, map_idx = 0, ret; 86 uint64_t phaddr; 87 struct mapped_pci_resource *uio_res = NULL; 88 struct mapped_pci_res_list *uio_res_list = 89 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 90 91 dev->intr_handle.fd = -1; 92 dev->intr_handle.uio_cfg_fd = -1; 93 94 /* secondary processes - use already recorded details */ 95 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 96 return pci_uio_map_secondary(dev); 97 98 /* allocate uio resource */ 99 ret = pci_uio_alloc_resource(dev, &uio_res); 100 if (ret) 101 return ret; 102 103 /* Map all BARs */ 104 for (i = 0; i != PCI_MAX_RESOURCE; i++) { 105 /* skip empty BAR */ 106 phaddr = dev->mem_resource[i].phys_addr; 107 if (phaddr == 0) 108 continue; 109 110 ret = pci_uio_map_resource_by_index(dev, i, 111 uio_res, map_idx); 112 if (ret) 113 goto error; 114 115 map_idx++; 116 } 117 118 uio_res->nb_maps = map_idx; 119 120 TAILQ_INSERT_TAIL(uio_res_list, uio_res, next); 121 122 return 0; 123 error: 124 for (i = 0; i < map_idx; i++) { 125 pci_unmap_resource(uio_res->maps[i].addr, 126 (size_t)uio_res->maps[i].size); 127 rte_free(uio_res->maps[i].path); 128 } 129 pci_uio_free_resource(dev, uio_res); 130 return -1; 131 } 132 133 static void 134 pci_uio_unmap(struct mapped_pci_resource *uio_res) 135 { 136 int i; 137 138 if (uio_res == NULL) 139 return; 140 141 for (i = 0; i != uio_res->nb_maps; i++) { 142 pci_unmap_resource(uio_res->maps[i].addr, 143 (size_t)uio_res->maps[i].size); 144 if (rte_eal_process_type() == RTE_PROC_PRIMARY) 145 rte_free(uio_res->maps[i].path); 146 } 147 } 148 149 static struct mapped_pci_resource * 150 pci_uio_find_resource(struct rte_pci_device *dev) 151 { 152 struct mapped_pci_resource *uio_res; 153 struct mapped_pci_res_list *uio_res_list = 154 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 155 156 if (dev == NULL) 157 return NULL; 158 159 TAILQ_FOREACH(uio_res, uio_res_list, next) { 160 161 /* skip this element if it doesn't match our PCI address */ 162 if (!rte_pci_addr_cmp(&uio_res->pci_addr, &dev->addr)) 163 return uio_res; 164 } 165 return NULL; 166 } 167 168 /* unmap the PCI resource of a PCI device in virtual memory */ 169 void 170 pci_uio_unmap_resource(struct rte_pci_device *dev) 171 { 172 struct mapped_pci_resource *uio_res; 173 struct mapped_pci_res_list *uio_res_list = 174 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 175 176 if (dev == NULL) 177 return; 178 179 /* find an entry for the device */ 180 uio_res = pci_uio_find_resource(dev); 181 if (uio_res == NULL) 182 return; 183 184 /* secondary processes - just free maps */ 185 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 186 return pci_uio_unmap(uio_res); 187 188 TAILQ_REMOVE(uio_res_list, uio_res, next); 189 190 /* unmap all resources */ 191 pci_uio_unmap(uio_res); 192 193 /* free uio resource */ 194 rte_free(uio_res); 195 196 /* close fd if in primary process */ 197 close(dev->intr_handle.fd); 198 if (dev->intr_handle.uio_cfg_fd >= 0) { 199 close(dev->intr_handle.uio_cfg_fd); 200 dev->intr_handle.uio_cfg_fd = -1; 201 } 202 203 dev->intr_handle.fd = -1; 204 dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 205 } 206