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