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