1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2018, Microsoft Corporation.
13 #include <rte_tailq.h>
15 #include <rte_malloc.h>
17 #include <rte_bus_vmbus.h>
21 static struct rte_tailq_elem vmbus_tailq = {
22 .name = "VMBUS_RESOURCE_LIST",
24 EAL_REGISTER_TAILQ(vmbus_tailq)
26 struct mapped_vmbus_resource *
27 vmbus_uio_find_resource(const struct rte_vmbus_device *dev)
29 struct mapped_vmbus_resource *uio_res;
30 struct mapped_vmbus_res_list *uio_res_list =
31 RTE_TAILQ_CAST(vmbus_tailq.head, mapped_vmbus_res_list);
36 TAILQ_FOREACH(uio_res, uio_res_list, next) {
37 if (rte_uuid_compare(uio_res->id, dev->device_id) == 0)
44 vmbus_uio_map_secondary(struct rte_vmbus_device *dev)
46 struct mapped_vmbus_resource *uio_res;
47 struct vmbus_channel *chan;
50 uio_res = vmbus_uio_find_resource(dev);
52 VMBUS_LOG(ERR, "Cannot find resource for device");
57 fd = open(uio_res->path, O_RDWR);
59 VMBUS_LOG(ERR, "Cannot open %s: %s",
60 uio_res->path, strerror(errno));
64 for (i = 0; i != uio_res->nb_maps; i++) {
66 off_t offset = i * rte_mem_page_size();
68 mapaddr = vmbus_map_resource(uio_res->maps[i].addr,
70 uio_res->maps[i].size, 0);
72 if (mapaddr == uio_res->maps[i].addr) {
73 dev->resource[i].addr = mapaddr;
74 continue; /* successful map */
77 if (mapaddr == MAP_FAILED)
79 "mmap resource %d in secondary failed", i);
82 "mmap resource %d address mismatch", i);
83 vmbus_unmap_resource(mapaddr, uio_res->maps[i].size);
90 /* fd is not needed in secondary process, close it */
93 /* Create and map primary channel */
94 if (vmbus_chan_create(dev, dev->relid, 0,
95 dev->monitor_id, &dev->primary)) {
96 VMBUS_LOG(ERR, "cannot create primary channel");
100 /* Create and map sub channels */
101 for (i = 0; i < uio_res->nb_subchannels; i++) {
102 if (rte_vmbus_subchan_open(dev->primary, &chan)) {
104 "failed to create subchannel at index %d", i);
105 goto failed_secondary;
112 while (!STAILQ_EMPTY(&dev->primary->subchannel_list)) {
113 chan = STAILQ_FIRST(&dev->primary->subchannel_list);
114 vmbus_unmap_resource(chan->txbr.vbr, chan->txbr.dsize * 2);
115 rte_vmbus_chan_close(chan);
117 rte_vmbus_chan_close(dev->primary);
120 for (i = 0; i != uio_res->nb_maps; i++) {
121 vmbus_unmap_resource(
122 uio_res->maps[i].addr, uio_res->maps[i].size);
129 vmbus_uio_map_primary(struct rte_vmbus_device *dev)
132 struct mapped_vmbus_resource *uio_res = NULL;
133 struct mapped_vmbus_res_list *uio_res_list =
134 RTE_TAILQ_CAST(vmbus_tailq.head, mapped_vmbus_res_list);
136 /* allocate uio resource */
137 ret = vmbus_uio_alloc_resource(dev, &uio_res);
141 /* Map the resources */
142 for (i = 0; i < VMBUS_MAX_RESOURCE; i++) {
143 /* stop at empty BAR */
144 if (dev->resource[i].len == 0)
147 ret = vmbus_uio_map_resource_by_index(dev, i, uio_res, 0);
152 uio_res->nb_maps = i;
154 TAILQ_INSERT_TAIL(uio_res_list, uio_res, next);
159 vmbus_unmap_resource(uio_res->maps[i].addr,
160 (size_t)uio_res->maps[i].size);
162 vmbus_uio_free_resource(dev, uio_res);
166 /* map the VMBUS resource of a VMBUS device in virtual memory */
168 vmbus_uio_map_resource(struct rte_vmbus_device *dev)
170 struct mapped_vmbus_resource *uio_res;
173 /* TODO: handle rescind */
174 if (rte_intr_fd_set(dev->intr_handle, -1))
177 if (rte_intr_dev_fd_set(dev->intr_handle, -1))
180 if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN))
183 /* secondary processes - use already recorded details */
184 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
185 ret = vmbus_uio_map_secondary(dev);
187 ret = vmbus_uio_map_primary(dev);
192 uio_res = vmbus_uio_find_resource(dev);
194 VMBUS_LOG(ERR, "can not find resources!");
198 if (uio_res->nb_maps <= HV_MON_PAGE_MAP) {
199 VMBUS_LOG(ERR, "VMBUS: only %u resources found!",
204 dev->int_page = (uint32_t *)((char *)uio_res->maps[HV_INT_PAGE_MAP].addr
205 + (rte_mem_page_size() >> 1));
206 dev->monitor_page = uio_res->maps[HV_MON_PAGE_MAP].addr;
211 vmbus_uio_unmap(struct mapped_vmbus_resource *uio_res)
218 for (i = 0; i < uio_res->nb_subchannels; i++) {
219 vmbus_unmap_resource(uio_res->subchannel_maps[i].addr,
220 uio_res->subchannel_maps[i].size);
223 for (i = 0; i != uio_res->nb_maps; i++) {
224 vmbus_unmap_resource(uio_res->maps[i].addr,
225 (size_t)uio_res->maps[i].size);
229 /* unmap the VMBUS resource of a VMBUS device in virtual memory */
231 vmbus_uio_unmap_resource(struct rte_vmbus_device *dev)
233 struct mapped_vmbus_resource *uio_res;
234 struct mapped_vmbus_res_list *uio_res_list =
235 RTE_TAILQ_CAST(vmbus_tailq.head, mapped_vmbus_res_list);
240 /* find an entry for the device */
241 uio_res = vmbus_uio_find_resource(dev);
245 /* secondary processes - just free maps */
246 if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
247 vmbus_uio_unmap(uio_res);
248 rte_free(dev->primary);
252 TAILQ_REMOVE(uio_res_list, uio_res, next);
254 /* unmap all resources */
255 vmbus_uio_unmap(uio_res);
257 /* free uio resource */
260 /* close fd if in primary process */
261 if (rte_intr_fd_get(dev->intr_handle) >= 0)
262 close(rte_intr_fd_get(dev->intr_handle));
264 if (rte_intr_dev_fd_get(dev->intr_handle) >= 0) {
265 close(rte_intr_dev_fd_get(dev->intr_handle));
266 rte_intr_dev_fd_set(dev->intr_handle, -1);
269 rte_intr_fd_set(dev->intr_handle, -1);
270 rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);