]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include <fcntl.h> | |
35 | #include <string.h> | |
36 | #include <unistd.h> | |
37 | #include <sys/types.h> | |
38 | #include <sys/stat.h> | |
39 | #include <sys/mman.h> | |
40 | ||
41 | #include <rte_eal.h> | |
42 | #include <rte_tailq.h> | |
43 | #include <rte_log.h> | |
44 | #include <rte_malloc.h> | |
45 | ||
46 | #include "eal_private.h" | |
47 | ||
48 | static struct rte_tailq_elem rte_uio_tailq = { | |
49 | .name = "UIO_RESOURCE_LIST", | |
50 | }; | |
51 | EAL_REGISTER_TAILQ(rte_uio_tailq) | |
52 | ||
53 | static int | |
54 | pci_uio_map_secondary(struct rte_pci_device *dev) | |
55 | { | |
56 | int fd, i, j; | |
57 | struct mapped_pci_resource *uio_res; | |
58 | struct mapped_pci_res_list *uio_res_list = | |
59 | RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); | |
60 | ||
61 | TAILQ_FOREACH(uio_res, uio_res_list, next) { | |
62 | ||
63 | /* skip this element if it doesn't match our PCI address */ | |
64 | if (rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr)) | |
65 | continue; | |
66 | ||
67 | for (i = 0; i != uio_res->nb_maps; i++) { | |
68 | /* | |
69 | * open devname, to mmap it | |
70 | */ | |
71 | fd = open(uio_res->maps[i].path, O_RDWR); | |
72 | if (fd < 0) { | |
73 | RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", | |
74 | uio_res->maps[i].path, strerror(errno)); | |
75 | return -1; | |
76 | } | |
77 | ||
78 | void *mapaddr = pci_map_resource(uio_res->maps[i].addr, | |
79 | fd, (off_t)uio_res->maps[i].offset, | |
80 | (size_t)uio_res->maps[i].size, 0); | |
81 | /* fd is not needed in slave process, close it */ | |
82 | close(fd); | |
83 | if (mapaddr != uio_res->maps[i].addr) { | |
84 | RTE_LOG(ERR, EAL, | |
85 | "Cannot mmap device resource file %s to address: %p\n", | |
86 | uio_res->maps[i].path, | |
87 | uio_res->maps[i].addr); | |
88 | if (mapaddr != MAP_FAILED) { | |
89 | /* unmap addrs correctly mapped */ | |
90 | for (j = 0; j < i; j++) | |
91 | pci_unmap_resource( | |
92 | uio_res->maps[j].addr, | |
93 | (size_t)uio_res->maps[j].size); | |
94 | /* unmap addr wrongly mapped */ | |
95 | pci_unmap_resource(mapaddr, | |
96 | (size_t)uio_res->maps[i].size); | |
97 | } | |
98 | return -1; | |
99 | } | |
100 | } | |
101 | return 0; | |
102 | } | |
103 | ||
104 | RTE_LOG(ERR, EAL, "Cannot find resource for device\n"); | |
105 | return 1; | |
106 | } | |
107 | ||
108 | /* map the PCI resource of a PCI device in virtual memory */ | |
109 | int | |
110 | pci_uio_map_resource(struct rte_pci_device *dev) | |
111 | { | |
112 | int i, map_idx = 0, ret; | |
113 | uint64_t phaddr; | |
114 | struct mapped_pci_resource *uio_res = NULL; | |
115 | struct mapped_pci_res_list *uio_res_list = | |
116 | RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); | |
117 | ||
118 | dev->intr_handle.fd = -1; | |
119 | dev->intr_handle.uio_cfg_fd = -1; | |
120 | dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; | |
121 | ||
122 | /* secondary processes - use already recorded details */ | |
123 | if (rte_eal_process_type() != RTE_PROC_PRIMARY) | |
124 | return pci_uio_map_secondary(dev); | |
125 | ||
126 | /* allocate uio resource */ | |
127 | ret = pci_uio_alloc_resource(dev, &uio_res); | |
128 | if (ret) | |
129 | return ret; | |
130 | ||
131 | /* Map all BARs */ | |
132 | for (i = 0; i != PCI_MAX_RESOURCE; i++) { | |
133 | /* skip empty BAR */ | |
134 | phaddr = dev->mem_resource[i].phys_addr; | |
135 | if (phaddr == 0) | |
136 | continue; | |
137 | ||
138 | ret = pci_uio_map_resource_by_index(dev, i, | |
139 | uio_res, map_idx); | |
140 | if (ret) | |
141 | goto error; | |
142 | ||
143 | map_idx++; | |
144 | } | |
145 | ||
146 | uio_res->nb_maps = map_idx; | |
147 | ||
148 | TAILQ_INSERT_TAIL(uio_res_list, uio_res, next); | |
149 | ||
150 | return 0; | |
151 | error: | |
152 | for (i = 0; i < map_idx; i++) { | |
153 | pci_unmap_resource(uio_res->maps[i].addr, | |
154 | (size_t)uio_res->maps[i].size); | |
155 | rte_free(uio_res->maps[i].path); | |
156 | } | |
157 | pci_uio_free_resource(dev, uio_res); | |
158 | return -1; | |
159 | } | |
160 | ||
161 | static void | |
162 | pci_uio_unmap(struct mapped_pci_resource *uio_res) | |
163 | { | |
164 | int i; | |
165 | ||
166 | if (uio_res == NULL) | |
167 | return; | |
168 | ||
169 | for (i = 0; i != uio_res->nb_maps; i++) { | |
170 | pci_unmap_resource(uio_res->maps[i].addr, | |
171 | (size_t)uio_res->maps[i].size); | |
172 | if (rte_eal_process_type() == RTE_PROC_PRIMARY) | |
173 | rte_free(uio_res->maps[i].path); | |
174 | } | |
175 | } | |
176 | ||
177 | static struct mapped_pci_resource * | |
178 | pci_uio_find_resource(struct rte_pci_device *dev) | |
179 | { | |
180 | struct mapped_pci_resource *uio_res; | |
181 | struct mapped_pci_res_list *uio_res_list = | |
182 | RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); | |
183 | ||
184 | if (dev == NULL) | |
185 | return NULL; | |
186 | ||
187 | TAILQ_FOREACH(uio_res, uio_res_list, next) { | |
188 | ||
189 | /* skip this element if it doesn't match our PCI address */ | |
190 | if (!rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr)) | |
191 | return uio_res; | |
192 | } | |
193 | return NULL; | |
194 | } | |
195 | ||
196 | /* unmap the PCI resource of a PCI device in virtual memory */ | |
197 | void | |
198 | pci_uio_unmap_resource(struct rte_pci_device *dev) | |
199 | { | |
200 | struct mapped_pci_resource *uio_res; | |
201 | struct mapped_pci_res_list *uio_res_list = | |
202 | RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); | |
203 | ||
204 | if (dev == NULL) | |
205 | return; | |
206 | ||
207 | /* find an entry for the device */ | |
208 | uio_res = pci_uio_find_resource(dev); | |
209 | if (uio_res == NULL) | |
210 | return; | |
211 | ||
212 | /* secondary processes - just free maps */ | |
213 | if (rte_eal_process_type() != RTE_PROC_PRIMARY) | |
214 | return pci_uio_unmap(uio_res); | |
215 | ||
216 | TAILQ_REMOVE(uio_res_list, uio_res, next); | |
217 | ||
218 | /* unmap all resources */ | |
219 | pci_uio_unmap(uio_res); | |
220 | ||
221 | /* free uio resource */ | |
222 | rte_free(uio_res); | |
223 | ||
224 | /* close fd if in primary process */ | |
225 | close(dev->intr_handle.fd); | |
226 | if (dev->intr_handle.uio_cfg_fd >= 0) { | |
227 | close(dev->intr_handle.uio_cfg_fd); | |
228 | dev->intr_handle.uio_cfg_fd = -1; | |
229 | } | |
230 | ||
231 | dev->intr_handle.fd = -1; | |
232 | dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; | |
233 | } |