c47f95fb0309dfde8902e089ebca7b4a277b0bc4
[dpdk.git] / drivers / mempool / octeontx2 / otx2_mempool.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_atomic.h>
6 #include <rte_bus_pci.h>
7 #include <rte_common.h>
8 #include <rte_eal.h>
9 #include <rte_io.h>
10 #include <rte_malloc.h>
11 #include <rte_mbuf_pool_ops.h>
12 #include <rte_pci.h>
13
14 #include "otx2_common.h"
15 #include "otx2_dev.h"
16 #include "otx2_mempool.h"
17
18 #define OTX2_NPA_DEV_NAME       RTE_STR(otx2_npa_dev_)
19 #define OTX2_NPA_DEV_NAME_LEN   (sizeof(OTX2_NPA_DEV_NAME) + PCI_PRI_STR_SIZE)
20
21 static inline int
22 npa_lf_alloc(struct otx2_npa_lf *lf)
23 {
24         struct otx2_mbox *mbox = lf->mbox;
25         struct npa_lf_alloc_req *req;
26         struct npa_lf_alloc_rsp *rsp;
27         int rc;
28
29         req = otx2_mbox_alloc_msg_npa_lf_alloc(mbox);
30         req->aura_sz = lf->aura_sz;
31         req->nr_pools = lf->nr_pools;
32
33         rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
34         if (rc)
35                 return NPA_LF_ERR_ALLOC;
36
37         lf->stack_pg_ptrs = rsp->stack_pg_ptrs;
38         lf->stack_pg_bytes = rsp->stack_pg_bytes;
39         lf->qints = rsp->qints;
40
41         return 0;
42 }
43
44 static int
45 npa_lf_free(struct otx2_mbox *mbox)
46 {
47         otx2_mbox_alloc_msg_npa_lf_free(mbox);
48
49         return otx2_mbox_process(mbox);
50 }
51
52 static int
53 npa_lf_init(struct otx2_npa_lf *lf, uintptr_t base, uint8_t aura_sz,
54             uint32_t nr_pools, struct otx2_mbox *mbox)
55 {
56         uint32_t i, bmp_sz;
57         int rc;
58
59         /* Sanity checks */
60         if (!lf || !base || !mbox || !nr_pools)
61                 return NPA_LF_ERR_PARAM;
62
63         if (base & AURA_ID_MASK)
64                 return NPA_LF_ERR_BASE_INVALID;
65
66         if (aura_sz == NPA_AURA_SZ_0 || aura_sz >= NPA_AURA_SZ_MAX)
67                 return NPA_LF_ERR_PARAM;
68
69         memset(lf, 0x0, sizeof(*lf));
70         lf->base = base;
71         lf->aura_sz = aura_sz;
72         lf->nr_pools = nr_pools;
73         lf->mbox = mbox;
74
75         rc = npa_lf_alloc(lf);
76         if (rc)
77                 goto exit;
78
79         bmp_sz = rte_bitmap_get_memory_footprint(nr_pools);
80
81         /* Allocate memory for bitmap */
82         lf->npa_bmp_mem = rte_zmalloc("npa_bmp_mem", bmp_sz,
83                                         RTE_CACHE_LINE_SIZE);
84         if (lf->npa_bmp_mem == NULL) {
85                 rc = -ENOMEM;
86                 goto lf_free;
87         }
88
89         /* Initialize pool resource bitmap array */
90         lf->npa_bmp = rte_bitmap_init(nr_pools, lf->npa_bmp_mem, bmp_sz);
91         if (lf->npa_bmp == NULL) {
92                 rc = -EINVAL;
93                 goto bmap_mem_free;
94         }
95
96         /* Mark all pools available */
97         for (i = 0; i < nr_pools; i++)
98                 rte_bitmap_set(lf->npa_bmp, i);
99
100         /* Allocate memory for qint context */
101         lf->npa_qint_mem = rte_zmalloc("npa_qint_mem",
102                         sizeof(struct otx2_npa_qint) * nr_pools, 0);
103         if (lf->npa_qint_mem == NULL) {
104                 rc = -ENOMEM;
105                 goto bmap_free;
106         }
107
108         /* Allocate memory for nap_aura_lim memory */
109         lf->aura_lim = rte_zmalloc("npa_aura_lim_mem",
110                         sizeof(struct npa_aura_lim) * nr_pools, 0);
111         if (lf->aura_lim == NULL) {
112                 rc = -ENOMEM;
113                 goto qint_free;
114         }
115
116         /* Init aura start & end limits */
117         for (i = 0; i < nr_pools; i++) {
118                 lf->aura_lim[i].ptr_start = UINT64_MAX;
119                 lf->aura_lim[i].ptr_end = 0x0ull;
120         }
121
122         return 0;
123
124 qint_free:
125         rte_free(lf->npa_qint_mem);
126 bmap_free:
127         rte_bitmap_free(lf->npa_bmp);
128 bmap_mem_free:
129         rte_free(lf->npa_bmp_mem);
130 lf_free:
131         npa_lf_free(lf->mbox);
132 exit:
133         return rc;
134 }
135
136 static int
137 npa_lf_fini(struct otx2_npa_lf *lf)
138 {
139         if (!lf)
140                 return NPA_LF_ERR_PARAM;
141
142         rte_free(lf->aura_lim);
143         rte_free(lf->npa_qint_mem);
144         rte_bitmap_free(lf->npa_bmp);
145         rte_free(lf->npa_bmp_mem);
146
147         return npa_lf_free(lf->mbox);
148
149 }
150
151 static inline uint32_t
152 otx2_aura_size_to_u32(uint8_t val)
153 {
154         if (val == NPA_AURA_SZ_0)
155                 return 128;
156         if (val >= NPA_AURA_SZ_MAX)
157                 return BIT_ULL(20);
158
159         return 1 << (val + 6);
160 }
161
162 static inline int
163 npa_lf_attach(struct otx2_mbox *mbox)
164 {
165         struct rsrc_attach_req *req;
166
167         req = otx2_mbox_alloc_msg_attach_resources(mbox);
168         req->npalf = true;
169
170         return otx2_mbox_process(mbox);
171 }
172
173 static inline int
174 npa_lf_detach(struct otx2_mbox *mbox)
175 {
176         struct rsrc_detach_req *req;
177
178         req = otx2_mbox_alloc_msg_detach_resources(mbox);
179         req->npalf = true;
180
181         return otx2_mbox_process(mbox);
182 }
183
184 static inline int
185 npa_lf_get_msix_offset(struct otx2_mbox *mbox, uint16_t *npa_msixoff)
186 {
187         struct msix_offset_rsp *msix_rsp;
188         int rc;
189
190         /* Get NPA and NIX MSIX vector offsets */
191         otx2_mbox_alloc_msg_msix_offset(mbox);
192
193         rc = otx2_mbox_process_msg(mbox, (void *)&msix_rsp);
194
195         *npa_msixoff = msix_rsp->npa_msixoff;
196
197         return rc;
198 }
199
200 /**
201  * @internal
202  * Finalize NPA LF.
203  */
204 int
205 otx2_npa_lf_fini(void)
206 {
207         struct otx2_idev_cfg *idev;
208         int rc = 0;
209
210         idev = otx2_intra_dev_get_cfg();
211         if (idev == NULL)
212                 return -ENOMEM;
213
214         if (rte_atomic16_add_return(&idev->npa_refcnt, -1) == 0) {
215                 otx2_npa_unregister_irqs(idev->npa_lf);
216                 rc |= npa_lf_fini(idev->npa_lf);
217                 rc |= npa_lf_detach(idev->npa_lf->mbox);
218                 otx2_npa_set_defaults(idev);
219         }
220
221         return rc;
222 }
223
224 /**
225  * @internal
226  * Initialize NPA LF.
227  */
228 int
229 otx2_npa_lf_init(struct rte_pci_device *pci_dev, void *otx2_dev)
230 {
231         struct otx2_dev *dev = otx2_dev;
232         struct otx2_idev_cfg *idev;
233         struct otx2_npa_lf *lf;
234         uint16_t npa_msixoff;
235         uint32_t nr_pools;
236         uint8_t aura_sz;
237         int rc;
238
239         idev = otx2_intra_dev_get_cfg();
240         if (idev == NULL)
241                 return -ENOMEM;
242
243         /* Is NPA LF initialized by any another driver? */
244         if (rte_atomic16_add_return(&idev->npa_refcnt, 1) == 1) {
245
246                 rc = npa_lf_attach(dev->mbox);
247                 if (rc)
248                         goto fail;
249
250                 rc = npa_lf_get_msix_offset(dev->mbox, &npa_msixoff);
251                 if (rc)
252                         goto npa_detach;
253
254                 aura_sz = NPA_AURA_SZ_128;
255                 nr_pools = otx2_aura_size_to_u32(aura_sz);
256
257                 lf = &dev->npalf;
258                 rc = npa_lf_init(lf, dev->bar2 + (RVU_BLOCK_ADDR_NPA << 20),
259                                         aura_sz, nr_pools, dev->mbox);
260
261                 if (rc)
262                         goto npa_detach;
263
264                 lf->pf_func = dev->pf_func;
265                 lf->npa_msixoff = npa_msixoff;
266                 lf->intr_handle = &pci_dev->intr_handle;
267                 lf->pci_dev = pci_dev;
268
269                 idev->npa_pf_func = dev->pf_func;
270                 idev->npa_lf = lf;
271                 rte_smp_wmb();
272                 rc = otx2_npa_register_irqs(lf);
273                 if (rc)
274                         goto npa_fini;
275
276                 rte_mbuf_set_platform_mempool_ops("octeontx2_npa");
277                 otx2_npa_dbg("npa_lf=%p pools=%d sz=%d pf_func=0x%x msix=0x%x",
278                              lf, nr_pools, aura_sz, lf->pf_func, npa_msixoff);
279         }
280
281         return 0;
282
283 npa_fini:
284         npa_lf_fini(idev->npa_lf);
285 npa_detach:
286         npa_lf_detach(dev->mbox);
287 fail:
288         rte_atomic16_dec(&idev->npa_refcnt);
289         return rc;
290 }
291
292 static inline char*
293 otx2_npa_dev_to_name(struct rte_pci_device *pci_dev, char *name)
294 {
295         snprintf(name, OTX2_NPA_DEV_NAME_LEN,
296                  OTX2_NPA_DEV_NAME  PCI_PRI_FMT,
297                  pci_dev->addr.domain, pci_dev->addr.bus,
298                  pci_dev->addr.devid, pci_dev->addr.function);
299
300         return name;
301 }
302
303 static int
304 otx2_npa_init(struct rte_pci_device *pci_dev)
305 {
306         char name[OTX2_NPA_DEV_NAME_LEN];
307         const struct rte_memzone *mz;
308         struct otx2_dev *dev;
309         int rc = -ENOMEM;
310
311         mz = rte_memzone_reserve_aligned(otx2_npa_dev_to_name(pci_dev, name),
312                                          sizeof(*dev), SOCKET_ID_ANY,
313                                          0, OTX2_ALIGN);
314         if (mz == NULL)
315                 goto error;
316
317         dev = mz->addr;
318
319         /* Initialize the base otx2_dev object */
320         rc = otx2_dev_init(pci_dev, dev);
321         if (rc)
322                 goto malloc_fail;
323
324         /* Grab the NPA LF if required */
325         rc = otx2_npa_lf_init(pci_dev, dev);
326         if (rc)
327                 goto dev_uninit;
328
329         dev->drv_inited = true;
330         return 0;
331
332 dev_uninit:
333         otx2_npa_lf_fini();
334         otx2_dev_fini(pci_dev, dev);
335 malloc_fail:
336         rte_memzone_free(mz);
337 error:
338         otx2_err("Failed to initialize npa device rc=%d", rc);
339         return rc;
340 }
341
342 static int
343 otx2_npa_fini(struct rte_pci_device *pci_dev)
344 {
345         char name[OTX2_NPA_DEV_NAME_LEN];
346         const struct rte_memzone *mz;
347         struct otx2_dev *dev;
348
349         mz = rte_memzone_lookup(otx2_npa_dev_to_name(pci_dev, name));
350         if (mz == NULL)
351                 return -EINVAL;
352
353         dev = mz->addr;
354         if (!dev->drv_inited)
355                 goto dev_fini;
356
357         dev->drv_inited = false;
358         otx2_npa_lf_fini();
359
360 dev_fini:
361         if (otx2_npa_lf_active(dev)) {
362                 otx2_info("%s: common resource in use by other devices",
363                           pci_dev->name);
364                 return -EAGAIN;
365         }
366
367         otx2_dev_fini(pci_dev, dev);
368         rte_memzone_free(mz);
369
370         return 0;
371 }
372
373 static int
374 npa_remove(struct rte_pci_device *pci_dev)
375 {
376         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
377                 return 0;
378
379         return otx2_npa_fini(pci_dev);
380 }
381
382 static int
383 npa_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
384 {
385         RTE_SET_USED(pci_drv);
386
387         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
388                 return 0;
389
390         return otx2_npa_init(pci_dev);
391 }
392
393 static const struct rte_pci_id pci_npa_map[] = {
394         {
395                 RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
396                                         PCI_DEVID_OCTEONTX2_RVU_NPA_PF)
397         },
398         {
399                 RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
400                                         PCI_DEVID_OCTEONTX2_RVU_NPA_VF)
401         },
402         {
403                 .vendor_id = 0,
404         },
405 };
406
407 static struct rte_pci_driver pci_npa = {
408         .id_table = pci_npa_map,
409         .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA,
410         .probe = npa_probe,
411         .remove = npa_remove,
412 };
413
414 RTE_PMD_REGISTER_PCI(mempool_octeontx2, pci_npa);
415 RTE_PMD_REGISTER_PCI_TABLE(mempool_octeontx2, pci_npa_map);
416 RTE_PMD_REGISTER_KMOD_DEP(mempool_octeontx2, "vfio-pci");