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