xref: /dpdk/drivers/bus/pci/pci_common_uio.c (revision 847d78fb9530fff401bf167298aad22766a1f04a)
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