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