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 = 0, j, res_idx; 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 /* Map all BARs */ 41 for (res_idx = 0; res_idx != PCI_MAX_RESOURCE; res_idx++) { 42 /* skip empty BAR */ 43 if (dev->mem_resource[res_idx].phys_addr == 0) 44 continue; 45 46 if (i >= uio_res->nb_maps) 47 return -1; 48 49 /* 50 * open devname, to mmap it 51 */ 52 fd = open(uio_res->maps[i].path, O_RDWR); 53 if (fd < 0) { 54 PCI_LOG(ERR, "Cannot open %s: %s", 55 uio_res->maps[i].path, strerror(errno)); 56 return -1; 57 } 58 59 void *mapaddr = pci_map_resource(uio_res->maps[i].addr, 60 fd, (off_t)uio_res->maps[i].offset, 61 (size_t)uio_res->maps[i].size, 0); 62 63 /* fd is not needed in secondary process, close it */ 64 close(fd); 65 if (mapaddr != uio_res->maps[i].addr) { 66 PCI_LOG(ERR, "Cannot mmap device resource file %s to address: %p", 67 uio_res->maps[i].path, 68 uio_res->maps[i].addr); 69 if (mapaddr != NULL) { 70 /* unmap addrs correctly mapped */ 71 for (j = 0; j < i; j++) 72 pci_unmap_resource( 73 uio_res->maps[j].addr, 74 (size_t)uio_res->maps[j].size); 75 /* unmap addr wrongly mapped */ 76 pci_unmap_resource(mapaddr, 77 (size_t)uio_res->maps[i].size); 78 } 79 return -1; 80 } 81 dev->mem_resource[res_idx].addr = mapaddr; 82 83 i++; 84 } 85 return 0; 86 } 87 88 PCI_LOG(ERR, "Cannot find resource for device"); 89 return 1; 90 } 91 92 /* map the PCI resource of a PCI device in virtual memory */ 93 int 94 pci_uio_map_resource(struct rte_pci_device *dev) 95 { 96 int i, map_idx = 0, ret; 97 uint64_t phaddr; 98 struct mapped_pci_resource *uio_res = NULL; 99 struct mapped_pci_res_list *uio_res_list = 100 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 101 102 if (rte_intr_fd_set(dev->intr_handle, -1)) 103 return -1; 104 105 if (rte_intr_dev_fd_set(dev->intr_handle, -1)) 106 return -1; 107 108 /* allocate uio resource */ 109 ret = pci_uio_alloc_resource(dev, &uio_res); 110 if (ret) 111 return ret; 112 113 /* secondary processes - use already recorded details */ 114 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 115 return pci_uio_map_secondary(dev); 116 117 /* Map all BARs */ 118 for (i = 0; i != PCI_MAX_RESOURCE; i++) { 119 /* skip empty BAR */ 120 phaddr = dev->mem_resource[i].phys_addr; 121 if (phaddr == 0) 122 continue; 123 124 ret = pci_uio_map_resource_by_index(dev, i, 125 uio_res, map_idx); 126 if (ret) 127 goto error; 128 129 map_idx++; 130 } 131 132 uio_res->nb_maps = map_idx; 133 134 TAILQ_INSERT_TAIL(uio_res_list, uio_res, next); 135 136 return 0; 137 error: 138 for (i = 0; i < map_idx; i++) { 139 pci_unmap_resource(uio_res->maps[i].addr, 140 (size_t)uio_res->maps[i].size); 141 rte_free(uio_res->maps[i].path); 142 } 143 pci_uio_free_resource(dev, uio_res); 144 return -1; 145 } 146 147 static void 148 pci_uio_unmap(struct mapped_pci_resource *uio_res) 149 { 150 int i; 151 152 if (uio_res == NULL) 153 return; 154 155 for (i = 0; i != uio_res->nb_maps; i++) { 156 pci_unmap_resource(uio_res->maps[i].addr, 157 (size_t)uio_res->maps[i].size); 158 if (rte_eal_process_type() == RTE_PROC_PRIMARY) 159 rte_free(uio_res->maps[i].path); 160 } 161 } 162 163 /* remap the PCI resource of a PCI device in anonymous virtual memory */ 164 int 165 pci_uio_remap_resource(struct rte_pci_device *dev) 166 { 167 int i; 168 void *map_address; 169 170 if (dev == NULL) 171 return -1; 172 173 /* Remap all BARs */ 174 for (i = 0; i != PCI_MAX_RESOURCE; i++) { 175 /* skip empty BAR */ 176 if (dev->mem_resource[i].phys_addr == 0) 177 continue; 178 map_address = mmap(dev->mem_resource[i].addr, 179 (size_t)dev->mem_resource[i].len, 180 PROT_READ | PROT_WRITE, 181 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 182 if (map_address == MAP_FAILED) { 183 PCI_LOG(ERR, "Cannot remap resource for device %s", dev->name); 184 return -1; 185 } 186 PCI_LOG(INFO, "Successful remap resource for device %s", dev->name); 187 } 188 189 return 0; 190 } 191 192 static struct mapped_pci_resource * 193 pci_uio_find_resource(struct rte_pci_device *dev) 194 { 195 struct mapped_pci_resource *uio_res; 196 struct mapped_pci_res_list *uio_res_list = 197 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 198 199 if (dev == NULL) 200 return NULL; 201 202 TAILQ_FOREACH(uio_res, uio_res_list, next) { 203 204 /* skip this element if it doesn't match our PCI address */ 205 if (!rte_pci_addr_cmp(&uio_res->pci_addr, &dev->addr)) 206 return uio_res; 207 } 208 return NULL; 209 } 210 211 /* unmap the PCI resource of a PCI device in virtual memory */ 212 void 213 pci_uio_unmap_resource(struct rte_pci_device *dev) 214 { 215 struct mapped_pci_resource *uio_res; 216 struct mapped_pci_res_list *uio_res_list = 217 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 218 int uio_cfg_fd; 219 220 if (dev == NULL) 221 return; 222 223 /* find an entry for the device */ 224 uio_res = pci_uio_find_resource(dev); 225 if (uio_res == NULL) 226 return; 227 228 /* close fd */ 229 if (rte_intr_fd_get(dev->intr_handle) >= 0) 230 close(rte_intr_fd_get(dev->intr_handle)); 231 uio_cfg_fd = rte_intr_dev_fd_get(dev->intr_handle); 232 if (uio_cfg_fd >= 0) { 233 close(uio_cfg_fd); 234 rte_intr_dev_fd_set(dev->intr_handle, -1); 235 } 236 237 rte_intr_fd_set(dev->intr_handle, -1); 238 rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); 239 240 /* secondary processes - just free maps */ 241 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 242 return pci_uio_unmap(uio_res); 243 244 TAILQ_REMOVE(uio_res_list, uio_res, next); 245 246 /* unmap all resources */ 247 pci_uio_unmap(uio_res); 248 249 /* free uio resource */ 250 rte_free(uio_res); 251 } 252