xref: /dpdk/drivers/vdpa/sfc/sfc_vdpa.c (revision c555d75201c3917108824a756db7095467829a11)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020-2021 Xilinx, Inc.
3  */
4 
5 #include <stdbool.h>
6 #include <stdint.h>
7 #include <pthread.h>
8 #include <sys/queue.h>
9 
10 #include <rte_common.h>
11 #include <rte_devargs.h>
12 #include <rte_errno.h>
13 #include <rte_kvargs.h>
14 #include <rte_string_fns.h>
15 #include <rte_vfio.h>
16 #include <rte_vhost.h>
17 
18 #include "efx.h"
19 #include "sfc_efx.h"
20 #include "sfc_vdpa.h"
21 
22 TAILQ_HEAD(sfc_vdpa_adapter_list_head, sfc_vdpa_adapter);
23 static struct sfc_vdpa_adapter_list_head sfc_vdpa_adapter_list =
24 	TAILQ_HEAD_INITIALIZER(sfc_vdpa_adapter_list);
25 
26 static pthread_mutex_t sfc_vdpa_adapter_list_lock = PTHREAD_MUTEX_INITIALIZER;
27 
28 struct sfc_vdpa_adapter *
sfc_vdpa_get_adapter_by_dev(struct rte_pci_device * pdev)29 sfc_vdpa_get_adapter_by_dev(struct rte_pci_device *pdev)
30 {
31 	bool found = false;
32 	struct sfc_vdpa_adapter *sva;
33 
34 	pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
35 
36 	TAILQ_FOREACH(sva, &sfc_vdpa_adapter_list, next) {
37 		if (pdev == sva->pdev) {
38 			found = true;
39 			break;
40 		}
41 	}
42 
43 	pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
44 
45 	return found ? sva : NULL;
46 }
47 
48 struct sfc_vdpa_ops_data *
sfc_vdpa_get_data_by_dev(struct rte_vdpa_device * vdpa_dev)49 sfc_vdpa_get_data_by_dev(struct rte_vdpa_device *vdpa_dev)
50 {
51 	bool found = false;
52 	struct sfc_vdpa_adapter *sva;
53 
54 	pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
55 
56 	TAILQ_FOREACH(sva, &sfc_vdpa_adapter_list, next) {
57 		if (vdpa_dev == sva->ops_data->vdpa_dev) {
58 			found = true;
59 			break;
60 		}
61 	}
62 
63 	pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
64 
65 	return found ? sva->ops_data : NULL;
66 }
67 
68 static int
sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter * sva)69 sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
70 {
71 	struct rte_pci_device *dev = sva->pdev;
72 	char dev_name[RTE_DEV_NAME_MAX_LEN] = {0};
73 	int rc;
74 
75 	rte_pci_device_name(&dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
76 
77 	sva->vfio_container_fd = rte_vfio_container_create();
78 	if (sva->vfio_container_fd < 0)	{
79 		sfc_vdpa_err(sva, "failed to create VFIO container");
80 		goto fail_container_create;
81 	}
82 
83 	rc = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
84 				    &sva->iommu_group_num);
85 	if (rc <= 0) {
86 		sfc_vdpa_err(sva, "failed to get IOMMU group for %s : %s",
87 			     dev_name, rte_strerror(-rc));
88 		goto fail_get_group_num;
89 	}
90 
91 	sva->vfio_group_fd =
92 		rte_vfio_container_group_bind(sva->vfio_container_fd,
93 					      sva->iommu_group_num);
94 	if (sva->vfio_group_fd < 0) {
95 		sfc_vdpa_err(sva,
96 			     "failed to bind IOMMU group %d to container %d",
97 			     sva->iommu_group_num, sva->vfio_container_fd);
98 		goto fail_group_bind;
99 	}
100 
101 	if (rte_pci_map_device(dev) != 0) {
102 		sfc_vdpa_err(sva, "failed to map PCI device %s : %s",
103 			     dev_name, rte_strerror(rte_errno));
104 		goto fail_pci_map_device;
105 	}
106 
107 	sva->vfio_dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
108 
109 	return 0;
110 
111 fail_pci_map_device:
112 	if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
113 					sva->iommu_group_num) != 0) {
114 		sfc_vdpa_err(sva,
115 			     "failed to unbind IOMMU group %d from container %d",
116 			     sva->iommu_group_num, sva->vfio_container_fd);
117 	}
118 
119 fail_group_bind:
120 fail_get_group_num:
121 	if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
122 		sfc_vdpa_err(sva, "failed to destroy container %d",
123 			     sva->vfio_container_fd);
124 	}
125 
126 fail_container_create:
127 	return -1;
128 }
129 
130 static void
sfc_vdpa_vfio_teardown(struct sfc_vdpa_adapter * sva)131 sfc_vdpa_vfio_teardown(struct sfc_vdpa_adapter *sva)
132 {
133 	rte_pci_unmap_device(sva->pdev);
134 
135 	if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
136 					    sva->iommu_group_num) != 0) {
137 		sfc_vdpa_err(sva,
138 			     "failed to unbind IOMMU group %d from container %d",
139 			     sva->iommu_group_num, sva->vfio_container_fd);
140 	}
141 
142 	if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
143 		sfc_vdpa_err(sva,
144 			     "failed to destroy container %d",
145 			     sva->vfio_container_fd);
146 	}
147 }
148 
149 static int
sfc_vdpa_set_log_prefix(struct sfc_vdpa_adapter * sva)150 sfc_vdpa_set_log_prefix(struct sfc_vdpa_adapter *sva)
151 {
152 	struct rte_pci_device *pci_dev = sva->pdev;
153 	int ret;
154 
155 	ret = snprintf(sva->log_prefix, sizeof(sva->log_prefix),
156 		       "PMD: sfc_vdpa " PCI_PRI_FMT " : ",
157 		       pci_dev->addr.domain, pci_dev->addr.bus,
158 		       pci_dev->addr.devid, pci_dev->addr.function);
159 
160 	if (ret < 0 || ret >= (int)sizeof(sva->log_prefix)) {
161 		SFC_VDPA_GENERIC_LOG(ERR,
162 			"reserved log prefix is too short for " PCI_PRI_FMT,
163 			pci_dev->addr.domain, pci_dev->addr.bus,
164 			pci_dev->addr.devid, pci_dev->addr.function);
165 		return -EINVAL;
166 	}
167 
168 	return 0;
169 }
170 
171 uint32_t
sfc_vdpa_register_logtype(const struct rte_pci_addr * pci_addr,const char * lt_prefix_str,uint32_t ll_default)172 sfc_vdpa_register_logtype(const struct rte_pci_addr *pci_addr,
173 			  const char *lt_prefix_str, uint32_t ll_default)
174 {
175 	size_t lt_prefix_str_size = strlen(lt_prefix_str);
176 	size_t lt_str_size_max;
177 	char *lt_str = NULL;
178 	int ret;
179 
180 	if (SIZE_MAX - PCI_PRI_STR_SIZE - 1 > lt_prefix_str_size) {
181 		++lt_prefix_str_size; /* Reserve space for prefix separator */
182 		lt_str_size_max = lt_prefix_str_size + PCI_PRI_STR_SIZE + 1;
183 	} else {
184 		return sfc_vdpa_logtype_driver;
185 	}
186 
187 	lt_str = rte_zmalloc("logtype_str", lt_str_size_max, 0);
188 	if (lt_str == NULL)
189 		return sfc_vdpa_logtype_driver;
190 
191 	strncpy(lt_str, lt_prefix_str, lt_prefix_str_size);
192 	lt_str[lt_prefix_str_size - 1] = '.';
193 	rte_pci_device_name(pci_addr, lt_str + lt_prefix_str_size,
194 			    lt_str_size_max - lt_prefix_str_size);
195 	lt_str[lt_str_size_max - 1] = '\0';
196 
197 	ret = rte_log_register_type_and_pick_level(lt_str, ll_default);
198 	rte_free(lt_str);
199 
200 	return ret < 0 ? sfc_vdpa_logtype_driver : ret;
201 }
202 
203 static int
sfc_vdpa_kvargs_parse(struct sfc_vdpa_adapter * sva)204 sfc_vdpa_kvargs_parse(struct sfc_vdpa_adapter *sva)
205 {
206 	struct rte_pci_device *pci_dev = sva->pdev;
207 	struct rte_devargs *devargs = pci_dev->device.devargs;
208 	/*
209 	 * To get the device class a mandatory param 'class' is being
210 	 * used so included SFC_EFX_KVARG_DEV_CLASS in the param list.
211 	 */
212 	const char **params = (const char *[]){
213 		RTE_DEVARGS_KEY_CLASS,
214 		SFC_VDPA_MAC_ADDR,
215 		NULL,
216 	};
217 
218 	if (devargs == NULL)
219 		return 0;
220 
221 	sva->kvargs = rte_kvargs_parse(devargs->args, params);
222 	if (sva->kvargs == NULL)
223 		return -EINVAL;
224 
225 	return 0;
226 }
227 
228 static struct rte_pci_id pci_id_sfc_vdpa_efx_map[] = {
229 	{ RTE_PCI_DEVICE(EFX_PCI_VENID_XILINX, EFX_PCI_DEVID_RIVERHEAD_VF) },
230 	{ .vendor_id = 0, /* sentinel */ },
231 };
232 
233 static int
sfc_vdpa_pci_probe(struct rte_pci_driver * pci_drv __rte_unused,struct rte_pci_device * pci_dev)234 sfc_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
235 	struct rte_pci_device *pci_dev)
236 {
237 	struct sfc_vdpa_adapter *sva = NULL;
238 	uint32_t logtype_main;
239 	int ret = 0;
240 
241 	if (sfc_efx_dev_class_get(pci_dev->device.devargs) !=
242 			SFC_EFX_DEV_CLASS_VDPA) {
243 		SFC_VDPA_GENERIC_LOG(INFO,
244 			"Incompatible device class: skip probing, should be probed by other sfc driver.");
245 			return 1;
246 	}
247 
248 	/*
249 	 * It will not be probed in the secondary process. As device class
250 	 * is vdpa so return 0 to avoid probe by other sfc driver
251 	 */
252 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
253 		return 0;
254 
255 	logtype_main = sfc_vdpa_register_logtype(&pci_dev->addr,
256 						 SFC_VDPA_LOGTYPE_MAIN_STR,
257 						 RTE_LOG_NOTICE);
258 
259 	sva = rte_zmalloc("sfc_vdpa", sizeof(struct sfc_vdpa_adapter), 0);
260 	if (sva == NULL)
261 		goto fail_zmalloc;
262 
263 	sva->pdev = pci_dev;
264 	sva->logtype_main = logtype_main;
265 
266 	ret = sfc_vdpa_set_log_prefix(sva);
267 	if (ret != 0)
268 		goto fail_set_log_prefix;
269 
270 	ret = sfc_vdpa_kvargs_parse(sva);
271 	if (ret != 0)
272 		goto fail_kvargs_parse;
273 
274 	sfc_vdpa_log_init(sva, "entry");
275 
276 	sfc_vdpa_adapter_lock_init(sva);
277 
278 	sfc_vdpa_log_init(sva, "vfio init");
279 	if (sfc_vdpa_vfio_setup(sva) < 0) {
280 		sfc_vdpa_err(sva, "failed to setup device %s", pci_dev->name);
281 		goto fail_vfio_setup;
282 	}
283 
284 	sfc_vdpa_log_init(sva, "hw init");
285 	if (sfc_vdpa_hw_init(sva) != 0) {
286 		sfc_vdpa_err(sva, "failed to init HW %s", pci_dev->name);
287 		goto fail_hw_init;
288 	}
289 
290 	sfc_vdpa_log_init(sva, "dev init");
291 	sva->ops_data = sfc_vdpa_device_init(sva, SFC_VDPA_AS_VF);
292 	if (sva->ops_data == NULL) {
293 		sfc_vdpa_err(sva, "failed vDPA dev init %s", pci_dev->name);
294 		goto fail_dev_init;
295 	}
296 
297 	pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
298 	TAILQ_INSERT_TAIL(&sfc_vdpa_adapter_list, sva, next);
299 	pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
300 
301 	sfc_vdpa_log_init(sva, "done");
302 
303 	return 0;
304 
305 fail_dev_init:
306 	sfc_vdpa_hw_fini(sva);
307 
308 fail_hw_init:
309 	sfc_vdpa_vfio_teardown(sva);
310 
311 fail_vfio_setup:
312 	sfc_vdpa_adapter_lock_fini(sva);
313 
314 fail_kvargs_parse:
315 fail_set_log_prefix:
316 	rte_free(sva);
317 
318 fail_zmalloc:
319 	return -1;
320 }
321 
322 static int
sfc_vdpa_pci_remove(struct rte_pci_device * pci_dev)323 sfc_vdpa_pci_remove(struct rte_pci_device *pci_dev)
324 {
325 	struct sfc_vdpa_adapter *sva = NULL;
326 
327 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
328 		return -1;
329 
330 	sva = sfc_vdpa_get_adapter_by_dev(pci_dev);
331 	if (sva == NULL) {
332 		SFC_VDPA_GENERIC_LOG(INFO,
333 			"Invalid device: %s.", pci_dev->name);
334 		return -1;
335 	}
336 
337 	pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
338 	TAILQ_REMOVE(&sfc_vdpa_adapter_list, sva, next);
339 	pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
340 
341 	sfc_vdpa_device_fini(sva->ops_data);
342 
343 	sfc_vdpa_hw_fini(sva);
344 
345 	sfc_vdpa_vfio_teardown(sva);
346 
347 	sfc_vdpa_adapter_lock_fini(sva);
348 
349 	rte_free(sva);
350 
351 	return 0;
352 }
353 
354 static struct rte_pci_driver rte_sfc_vdpa = {
355 	.id_table = pci_id_sfc_vdpa_efx_map,
356 	.drv_flags = 0,
357 	.probe = sfc_vdpa_pci_probe,
358 	.remove = sfc_vdpa_pci_remove,
359 };
360 
361 RTE_PMD_REGISTER_PCI(net_sfc_vdpa, rte_sfc_vdpa);
362 RTE_PMD_REGISTER_PCI_TABLE(net_sfc_vdpa, pci_id_sfc_vdpa_efx_map);
363 RTE_PMD_REGISTER_KMOD_DEP(net_sfc_vdpa, "* vfio-pci");
364 RTE_LOG_REGISTER_SUFFIX(sfc_vdpa_logtype_driver, driver, NOTICE);
365