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