vdpa/sfc: support MAC filter config
[dpdk.git] / drivers / vdpa / sfc / sfc_vdpa_hw.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020-2021 Xilinx, Inc.
3  */
4
5 #include <unistd.h>
6
7 #include <rte_common.h>
8 #include <rte_errno.h>
9 #include <rte_vfio.h>
10 #include <rte_vhost.h>
11
12 #include "efx.h"
13 #include "sfc_vdpa.h"
14 #include "sfc_vdpa_ops.h"
15
16 extern uint32_t sfc_logtype_driver;
17
18 #ifndef PAGE_SIZE
19 #define PAGE_SIZE   (sysconf(_SC_PAGESIZE))
20 #endif
21
22 int
23 sfc_vdpa_dma_alloc(struct sfc_vdpa_adapter *sva, const char *name,
24                    size_t len, efsys_mem_t *esmp)
25 {
26         uint64_t mcdi_iova;
27         size_t mcdi_buff_size;
28         const struct rte_memzone *mz = NULL;
29         int numa_node = sva->pdev->device.numa_node;
30         int ret;
31
32         mcdi_buff_size = RTE_ALIGN_CEIL(len, PAGE_SIZE);
33
34         sfc_vdpa_log_init(sva, "name=%s, len=%zu", name, len);
35
36         mz = rte_memzone_reserve_aligned(name, mcdi_buff_size,
37                                          numa_node,
38                                          RTE_MEMZONE_IOVA_CONTIG,
39                                          PAGE_SIZE);
40         if (mz == NULL) {
41                 sfc_vdpa_err(sva, "cannot reserve memory for %s: len=%#x: %s",
42                              name, (unsigned int)len, rte_strerror(rte_errno));
43                 return -ENOMEM;
44         }
45
46         /* IOVA address for MCDI would be re-calculated if mapping
47          * using default IOVA would fail.
48          * TODO: Earlier there was no way to get valid IOVA range.
49          * Recently a patch has been submitted to get the IOVA range
50          * using ioctl. VFIO_IOMMU_GET_INFO. This patch is available
51          * in the kernel version >= 5.4. Support to get the default
52          * IOVA address for MCDI buffer using available IOVA range
53          * would be added later. Meanwhile default IOVA for MCDI buffer
54          * is kept at high mem at 2TB. In case of overlap new available
55          * addresses would be searched and same would be used.
56          */
57         mcdi_iova = SFC_VDPA_DEFAULT_MCDI_IOVA;
58
59         for (;;) {
60                 ret = rte_vfio_container_dma_map(sva->vfio_container_fd,
61                                                  (uint64_t)mz->addr, mcdi_iova,
62                                                  mcdi_buff_size);
63                 if (ret == 0)
64                         break;
65
66                 mcdi_iova = mcdi_iova >> 1;
67                 if (mcdi_iova < mcdi_buff_size) {
68                         sfc_vdpa_err(sva,
69                                      "DMA mapping failed for MCDI : %s",
70                                      rte_strerror(rte_errno));
71                         rte_memzone_free(mz);
72                         return ret;
73                 }
74         }
75
76         esmp->esm_addr = mcdi_iova;
77         esmp->esm_base = mz->addr;
78         sva->mcdi_buff_size = mcdi_buff_size;
79
80         sfc_vdpa_info(sva,
81                       "DMA name=%s len=%zu => virt=%p iova=0x%" PRIx64,
82                       name, len, esmp->esm_base, esmp->esm_addr);
83
84         return 0;
85 }
86
87 void
88 sfc_vdpa_dma_free(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp)
89 {
90         int ret;
91
92         sfc_vdpa_log_init(sva, "name=%s", esmp->esm_mz->name);
93
94         ret = rte_vfio_container_dma_unmap(sva->vfio_container_fd,
95                                            (uint64_t)esmp->esm_base,
96                                            esmp->esm_addr, sva->mcdi_buff_size);
97         if (ret < 0)
98                 sfc_vdpa_err(sva, "DMA unmap failed for MCDI : %s",
99                              rte_strerror(rte_errno));
100
101         sfc_vdpa_info(sva,
102                       "DMA free name=%s => virt=%p iova=0x%" PRIx64,
103                       esmp->esm_mz->name, esmp->esm_base, esmp->esm_addr);
104
105         rte_free((void *)(esmp->esm_base));
106
107         sva->mcdi_buff_size = 0;
108         memset(esmp, 0, sizeof(*esmp));
109 }
110
111 int
112 sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *ops_data, bool do_map)
113 {
114         uint32_t i, j;
115         int rc;
116         struct rte_vhost_memory *vhost_mem = NULL;
117         struct rte_vhost_mem_region *mem_reg = NULL;
118         int vfio_container_fd;
119         void *dev;
120
121         dev = ops_data->dev_handle;
122         vfio_container_fd =
123                 sfc_vdpa_adapter_by_dev_handle(dev)->vfio_container_fd;
124
125         rc = rte_vhost_get_mem_table(ops_data->vid, &vhost_mem);
126         if (rc < 0) {
127                 sfc_vdpa_err(dev,
128                              "failed to get VM memory layout");
129                 goto error;
130         }
131
132         for (i = 0; i < vhost_mem->nregions; i++) {
133                 mem_reg = &vhost_mem->regions[i];
134
135                 if (do_map) {
136                         rc = rte_vfio_container_dma_map(vfio_container_fd,
137                                                 mem_reg->host_user_addr,
138                                                 mem_reg->guest_phys_addr,
139                                                 mem_reg->size);
140                         if (rc < 0) {
141                                 sfc_vdpa_err(dev,
142                                              "DMA map failed : %s",
143                                              rte_strerror(rte_errno));
144                                 goto failed_vfio_dma_map;
145                         }
146                 } else {
147                         rc = rte_vfio_container_dma_unmap(vfio_container_fd,
148                                                 mem_reg->host_user_addr,
149                                                 mem_reg->guest_phys_addr,
150                                                 mem_reg->size);
151                         if (rc < 0) {
152                                 sfc_vdpa_err(dev,
153                                              "DMA unmap failed : %s",
154                                              rte_strerror(rte_errno));
155                                 goto error;
156                         }
157                 }
158         }
159
160         free(vhost_mem);
161
162         return 0;
163
164 failed_vfio_dma_map:
165         for (j = 0; j < i; j++) {
166                 mem_reg = &vhost_mem->regions[j];
167                 rte_vfio_container_dma_unmap(vfio_container_fd,
168                                              mem_reg->host_user_addr,
169                                              mem_reg->guest_phys_addr,
170                                              mem_reg->size);
171         }
172
173 error:
174         free(vhost_mem);
175
176         return rc;
177 }
178
179 static int
180 sfc_vdpa_mem_bar_init(struct sfc_vdpa_adapter *sva,
181                       const efx_bar_region_t *mem_ebrp)
182 {
183         struct rte_pci_device *pci_dev = sva->pdev;
184         efsys_bar_t *ebp = &sva->mem_bar;
185         struct rte_mem_resource *res =
186                 &pci_dev->mem_resource[mem_ebrp->ebr_index];
187
188         SFC_BAR_LOCK_INIT(ebp, pci_dev->name);
189         ebp->esb_rid = mem_ebrp->ebr_index;
190         ebp->esb_dev = pci_dev;
191         ebp->esb_base = res->addr;
192
193         return 0;
194 }
195
196 static void
197 sfc_vdpa_mem_bar_fini(struct sfc_vdpa_adapter *sva)
198 {
199         efsys_bar_t *ebp = &sva->mem_bar;
200
201         SFC_BAR_LOCK_DESTROY(ebp);
202         memset(ebp, 0, sizeof(*ebp));
203 }
204
205 static int
206 sfc_vdpa_nic_probe(struct sfc_vdpa_adapter *sva)
207 {
208         efx_nic_t *enp = sva->nic;
209         int rc;
210
211         rc = efx_nic_probe(enp, EFX_FW_VARIANT_DONT_CARE);
212         if (rc != 0)
213                 sfc_vdpa_err(sva, "nic probe failed: %s", rte_strerror(rc));
214
215         return rc;
216 }
217
218 static int
219 sfc_vdpa_estimate_resource_limits(struct sfc_vdpa_adapter *sva)
220 {
221         efx_drv_limits_t limits;
222         int rc;
223         uint32_t evq_allocated;
224         uint32_t rxq_allocated;
225         uint32_t txq_allocated;
226         uint32_t max_queue_cnt;
227
228         memset(&limits, 0, sizeof(limits));
229
230         /* Request at least one Rx and Tx queue */
231         limits.edl_min_rxq_count = 1;
232         limits.edl_min_txq_count = 1;
233         /* Management event queue plus event queue for Tx/Rx queue */
234         limits.edl_min_evq_count =
235                 1 + RTE_MAX(limits.edl_min_rxq_count, limits.edl_min_txq_count);
236
237         limits.edl_max_rxq_count = SFC_VDPA_MAX_QUEUE_PAIRS;
238         limits.edl_max_txq_count = SFC_VDPA_MAX_QUEUE_PAIRS;
239         limits.edl_max_evq_count = 1 + SFC_VDPA_MAX_QUEUE_PAIRS;
240
241         SFC_VDPA_ASSERT(limits.edl_max_evq_count >= limits.edl_min_rxq_count);
242         SFC_VDPA_ASSERT(limits.edl_max_rxq_count >= limits.edl_min_rxq_count);
243         SFC_VDPA_ASSERT(limits.edl_max_txq_count >= limits.edl_min_rxq_count);
244
245         /* Configure the minimum required resources needed for the
246          * driver to operate, and the maximum desired resources that the
247          * driver is capable of using.
248          */
249         sfc_vdpa_log_init(sva, "set drv limit");
250         efx_nic_set_drv_limits(sva->nic, &limits);
251
252         sfc_vdpa_log_init(sva, "init nic");
253         rc = efx_nic_init(sva->nic);
254         if (rc != 0) {
255                 sfc_vdpa_err(sva, "nic init failed: %s", rte_strerror(rc));
256                 goto fail_nic_init;
257         }
258
259         /* Find resource dimensions assigned by firmware to this function */
260         rc = efx_nic_get_vi_pool(sva->nic, &evq_allocated, &rxq_allocated,
261                                  &txq_allocated);
262         if (rc != 0) {
263                 sfc_vdpa_err(sva, "vi pool get failed: %s", rte_strerror(rc));
264                 goto fail_get_vi_pool;
265         }
266
267         /* It still may allocate more than maximum, ensure limit */
268         evq_allocated = RTE_MIN(evq_allocated, limits.edl_max_evq_count);
269         rxq_allocated = RTE_MIN(rxq_allocated, limits.edl_max_rxq_count);
270         txq_allocated = RTE_MIN(txq_allocated, limits.edl_max_txq_count);
271
272
273         max_queue_cnt = RTE_MIN(rxq_allocated, txq_allocated);
274         /* Subtract management EVQ not used for traffic */
275         max_queue_cnt = RTE_MIN(evq_allocated - 1, max_queue_cnt);
276
277         SFC_VDPA_ASSERT(max_queue_cnt > 0);
278
279         sva->max_queue_count = max_queue_cnt;
280
281         return 0;
282
283 fail_get_vi_pool:
284         efx_nic_fini(sva->nic);
285 fail_nic_init:
286         sfc_vdpa_log_init(sva, "failed: %s", rte_strerror(rc));
287         return rc;
288 }
289
290 int
291 sfc_vdpa_hw_init(struct sfc_vdpa_adapter *sva)
292 {
293         efx_bar_region_t mem_ebr;
294         efx_nic_t *enp;
295         int rc;
296
297         sfc_vdpa_log_init(sva, "entry");
298
299         sfc_vdpa_log_init(sva, "get family");
300         rc = sfc_efx_family(sva->pdev, &mem_ebr, &sva->family);
301         if (rc != 0)
302                 goto fail_family;
303         sfc_vdpa_log_init(sva,
304                           "family is %u, membar is %d,"
305                           "function control window offset is %#" PRIx64,
306                           sva->family, mem_ebr.ebr_index, mem_ebr.ebr_offset);
307
308         sfc_vdpa_log_init(sva, "init mem bar");
309         rc = sfc_vdpa_mem_bar_init(sva, &mem_ebr);
310         if (rc != 0)
311                 goto fail_mem_bar_init;
312
313         sfc_vdpa_log_init(sva, "create nic");
314         rte_spinlock_init(&sva->nic_lock);
315         rc = efx_nic_create(sva->family, (efsys_identifier_t *)sva,
316                             &sva->mem_bar, mem_ebr.ebr_offset,
317                             &sva->nic_lock, &enp);
318         if (rc != 0) {
319                 sfc_vdpa_err(sva, "nic create failed: %s", rte_strerror(rc));
320                 goto fail_nic_create;
321         }
322         sva->nic = enp;
323
324         sfc_vdpa_log_init(sva, "init mcdi");
325         rc = sfc_vdpa_mcdi_init(sva);
326         if (rc != 0) {
327                 sfc_vdpa_err(sva, "mcdi init failed: %s", rte_strerror(rc));
328                 goto fail_mcdi_init;
329         }
330
331         sfc_vdpa_log_init(sva, "probe nic");
332         rc = sfc_vdpa_nic_probe(sva);
333         if (rc != 0)
334                 goto fail_nic_probe;
335
336         sfc_vdpa_log_init(sva, "reset nic");
337         rc = efx_nic_reset(enp);
338         if (rc != 0) {
339                 sfc_vdpa_err(sva, "nic reset failed: %s", rte_strerror(rc));
340                 goto fail_nic_reset;
341         }
342
343         sfc_vdpa_log_init(sva, "estimate resource limits");
344         rc = sfc_vdpa_estimate_resource_limits(sva);
345         if (rc != 0)
346                 goto fail_estimate_rsrc_limits;
347
348         sfc_vdpa_log_init(sva, "init virtio");
349         rc = efx_virtio_init(enp);
350         if (rc != 0) {
351                 sfc_vdpa_err(sva, "virtio init failed: %s", rte_strerror(rc));
352                 goto fail_virtio_init;
353         }
354
355         sfc_vdpa_log_init(sva, "init filter");
356         rc = efx_filter_init(enp);
357         if (rc != 0) {
358                 sfc_vdpa_err(sva, "filter init failed: %s", rte_strerror(rc));
359                 goto fail_filter_init;
360         }
361
362         sfc_vdpa_log_init(sva, "done");
363
364         return 0;
365
366 fail_filter_init:
367         efx_virtio_fini(enp);
368
369 fail_virtio_init:
370         efx_nic_fini(enp);
371
372 fail_estimate_rsrc_limits:
373 fail_nic_reset:
374         efx_nic_unprobe(enp);
375
376 fail_nic_probe:
377         sfc_vdpa_mcdi_fini(sva);
378
379 fail_mcdi_init:
380         sfc_vdpa_log_init(sva, "destroy nic");
381         sva->nic = NULL;
382         efx_nic_destroy(enp);
383
384 fail_nic_create:
385         sfc_vdpa_mem_bar_fini(sva);
386
387 fail_mem_bar_init:
388 fail_family:
389         sfc_vdpa_log_init(sva, "failed: %s", rte_strerror(rc));
390         return rc;
391 }
392
393 void
394 sfc_vdpa_hw_fini(struct sfc_vdpa_adapter *sva)
395 {
396         efx_nic_t *enp = sva->nic;
397
398         sfc_vdpa_log_init(sva, "entry");
399
400         sfc_vdpa_log_init(sva, "virtio fini");
401         efx_virtio_fini(enp);
402
403         sfc_vdpa_log_init(sva, "unprobe nic");
404         efx_nic_unprobe(enp);
405
406         sfc_vdpa_log_init(sva, "mcdi fini");
407         sfc_vdpa_mcdi_fini(sva);
408
409         sfc_vdpa_log_init(sva, "nic fini");
410         efx_nic_fini(enp);
411
412         sfc_vdpa_log_init(sva, "destroy nic");
413         sva->nic = NULL;
414         efx_nic_destroy(enp);
415
416         sfc_vdpa_mem_bar_fini(sva);
417 }