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