mempool: introduce helpers for populate and required size
[dpdk.git] / drivers / mempool / octeontx2 / otx2_mempool_ops.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_mempool.h>
6 #include <rte_vect.h>
7
8 #include "otx2_mempool.h"
9
10 static int __hot
11 otx2_npa_enq(struct rte_mempool *mp, void * const *obj_table, unsigned int n)
12 {
13         unsigned int index; const uint64_t aura_handle = mp->pool_id;
14         const uint64_t reg = npa_lf_aura_handle_to_aura(aura_handle);
15         const uint64_t addr = npa_lf_aura_handle_to_base(aura_handle) +
16                                  NPA_LF_AURA_OP_FREE0;
17
18         for (index = 0; index < n; index++)
19                 otx2_store_pair((uint64_t)obj_table[index], reg, addr);
20
21         return 0;
22 }
23
24 static __rte_noinline int
25 npa_lf_aura_op_alloc_one(const int64_t wdata, int64_t * const addr,
26                          void **obj_table, uint8_t i)
27 {
28         uint8_t retry = 4;
29
30         do {
31                 obj_table[i] = (void *)otx2_atomic64_add_nosync(wdata, addr);
32                 if (obj_table[i] != NULL)
33                         return 0;
34
35         } while (retry--);
36
37         return -ENOENT;
38 }
39
40 #if defined(RTE_ARCH_ARM64)
41 static __rte_noinline int
42 npa_lf_aura_op_search_alloc(const int64_t wdata, int64_t * const addr,
43                 void **obj_table, unsigned int n)
44 {
45         uint8_t i;
46
47         for (i = 0; i < n; i++) {
48                 if (obj_table[i] != NULL)
49                         continue;
50                 if (npa_lf_aura_op_alloc_one(wdata, addr, obj_table, i))
51                         return -ENOENT;
52         }
53
54         return 0;
55 }
56
57 static __rte_noinline int
58 npa_lf_aura_op_alloc_bulk(const int64_t wdata, int64_t * const addr,
59                           unsigned int n, void **obj_table)
60 {
61         register const uint64_t wdata64 __asm("x26") = wdata;
62         register const uint64_t wdata128 __asm("x27") = wdata;
63         uint64x2_t failed = vdupq_n_u64(~0);
64
65         switch (n) {
66         case 32:
67         {
68                 asm volatile (
69                 ".cpu  generic+lse\n"
70                 "casp x0, x1, %[wdata64], %[wdata128], [%[loc]]\n"
71                 "casp x2, x3, %[wdata64], %[wdata128], [%[loc]]\n"
72                 "casp x4, x5, %[wdata64], %[wdata128], [%[loc]]\n"
73                 "casp x6, x7, %[wdata64], %[wdata128], [%[loc]]\n"
74                 "casp x8, x9, %[wdata64], %[wdata128], [%[loc]]\n"
75                 "casp x10, x11, %[wdata64], %[wdata128], [%[loc]]\n"
76                 "casp x12, x13, %[wdata64], %[wdata128], [%[loc]]\n"
77                 "casp x14, x15, %[wdata64], %[wdata128], [%[loc]]\n"
78                 "casp x16, x17, %[wdata64], %[wdata128], [%[loc]]\n"
79                 "casp x18, x19, %[wdata64], %[wdata128], [%[loc]]\n"
80                 "casp x20, x21, %[wdata64], %[wdata128], [%[loc]]\n"
81                 "casp x22, x23, %[wdata64], %[wdata128], [%[loc]]\n"
82                 "fmov d16, x0\n"
83                 "fmov v16.D[1], x1\n"
84                 "casp x0, x1, %[wdata64], %[wdata128], [%[loc]]\n"
85                 "fmov d17, x2\n"
86                 "fmov v17.D[1], x3\n"
87                 "casp x2, x3, %[wdata64], %[wdata128], [%[loc]]\n"
88                 "fmov d18, x4\n"
89                 "fmov v18.D[1], x5\n"
90                 "casp x4, x5, %[wdata64], %[wdata128], [%[loc]]\n"
91                 "fmov d19, x6\n"
92                 "fmov v19.D[1], x7\n"
93                 "casp x6, x7, %[wdata64], %[wdata128], [%[loc]]\n"
94                 "and %[failed].16B, %[failed].16B, v16.16B\n"
95                 "and %[failed].16B, %[failed].16B, v17.16B\n"
96                 "and %[failed].16B, %[failed].16B, v18.16B\n"
97                 "and %[failed].16B, %[failed].16B, v19.16B\n"
98                 "fmov d20, x8\n"
99                 "fmov v20.D[1], x9\n"
100                 "fmov d21, x10\n"
101                 "fmov v21.D[1], x11\n"
102                 "fmov d22, x12\n"
103                 "fmov v22.D[1], x13\n"
104                 "fmov d23, x14\n"
105                 "fmov v23.D[1], x15\n"
106                 "and %[failed].16B, %[failed].16B, v20.16B\n"
107                 "and %[failed].16B, %[failed].16B, v21.16B\n"
108                 "and %[failed].16B, %[failed].16B, v22.16B\n"
109                 "and %[failed].16B, %[failed].16B, v23.16B\n"
110                 "st1 { v16.2d, v17.2d, v18.2d, v19.2d}, [%[dst]], 64\n"
111                 "st1 { v20.2d, v21.2d, v22.2d, v23.2d}, [%[dst]], 64\n"
112                 "fmov d16, x16\n"
113                 "fmov v16.D[1], x17\n"
114                 "fmov d17, x18\n"
115                 "fmov v17.D[1], x19\n"
116                 "fmov d18, x20\n"
117                 "fmov v18.D[1], x21\n"
118                 "fmov d19, x22\n"
119                 "fmov v19.D[1], x23\n"
120                 "and %[failed].16B, %[failed].16B, v16.16B\n"
121                 "and %[failed].16B, %[failed].16B, v17.16B\n"
122                 "and %[failed].16B, %[failed].16B, v18.16B\n"
123                 "and %[failed].16B, %[failed].16B, v19.16B\n"
124                 "fmov d20, x0\n"
125                 "fmov v20.D[1], x1\n"
126                 "fmov d21, x2\n"
127                 "fmov v21.D[1], x3\n"
128                 "fmov d22, x4\n"
129                 "fmov v22.D[1], x5\n"
130                 "fmov d23, x6\n"
131                 "fmov v23.D[1], x7\n"
132                 "and %[failed].16B, %[failed].16B, v20.16B\n"
133                 "and %[failed].16B, %[failed].16B, v21.16B\n"
134                 "and %[failed].16B, %[failed].16B, v22.16B\n"
135                 "and %[failed].16B, %[failed].16B, v23.16B\n"
136                 "st1 { v16.2d, v17.2d, v18.2d, v19.2d}, [%[dst]], 64\n"
137                 "st1 { v20.2d, v21.2d, v22.2d, v23.2d}, [%[dst]], 64\n"
138                 : "+Q" (*addr), [failed] "=&w" (failed)
139                 : [wdata64] "r" (wdata64), [wdata128] "r" (wdata128),
140                 [dst] "r" (obj_table), [loc] "r" (addr)
141                 : "memory", "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
142                 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16",
143                 "x17", "x18", "x19", "x20", "x21", "x22", "x23", "v16", "v17",
144                 "v18", "v19", "v20", "v21", "v22", "v23"
145                 );
146                 break;
147         }
148         case 16:
149         {
150                 asm volatile (
151                 ".cpu  generic+lse\n"
152                 "casp x0, x1, %[wdata64], %[wdata128], [%[loc]]\n"
153                 "casp x2, x3, %[wdata64], %[wdata128], [%[loc]]\n"
154                 "casp x4, x5, %[wdata64], %[wdata128], [%[loc]]\n"
155                 "casp x6, x7, %[wdata64], %[wdata128], [%[loc]]\n"
156                 "casp x8, x9, %[wdata64], %[wdata128], [%[loc]]\n"
157                 "casp x10, x11, %[wdata64], %[wdata128], [%[loc]]\n"
158                 "casp x12, x13, %[wdata64], %[wdata128], [%[loc]]\n"
159                 "casp x14, x15, %[wdata64], %[wdata128], [%[loc]]\n"
160                 "fmov d16, x0\n"
161                 "fmov v16.D[1], x1\n"
162                 "fmov d17, x2\n"
163                 "fmov v17.D[1], x3\n"
164                 "fmov d18, x4\n"
165                 "fmov v18.D[1], x5\n"
166                 "fmov d19, x6\n"
167                 "fmov v19.D[1], x7\n"
168                 "and %[failed].16B, %[failed].16B, v16.16B\n"
169                 "and %[failed].16B, %[failed].16B, v17.16B\n"
170                 "and %[failed].16B, %[failed].16B, v18.16B\n"
171                 "and %[failed].16B, %[failed].16B, v19.16B\n"
172                 "fmov d20, x8\n"
173                 "fmov v20.D[1], x9\n"
174                 "fmov d21, x10\n"
175                 "fmov v21.D[1], x11\n"
176                 "fmov d22, x12\n"
177                 "fmov v22.D[1], x13\n"
178                 "fmov d23, x14\n"
179                 "fmov v23.D[1], x15\n"
180                 "and %[failed].16B, %[failed].16B, v20.16B\n"
181                 "and %[failed].16B, %[failed].16B, v21.16B\n"
182                 "and %[failed].16B, %[failed].16B, v22.16B\n"
183                 "and %[failed].16B, %[failed].16B, v23.16B\n"
184                 "st1 { v16.2d, v17.2d, v18.2d, v19.2d}, [%[dst]], 64\n"
185                 "st1 { v20.2d, v21.2d, v22.2d, v23.2d}, [%[dst]], 64\n"
186                 : "+Q" (*addr), [failed] "=&w" (failed)
187                 : [wdata64] "r" (wdata64), [wdata128] "r" (wdata128),
188                 [dst] "r" (obj_table), [loc] "r" (addr)
189                 : "memory", "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
190                 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "v16",
191                 "v17", "v18", "v19", "v20", "v21", "v22", "v23"
192                 );
193                 break;
194         }
195         case 8:
196         {
197                 asm volatile (
198                 ".cpu  generic+lse\n"
199                 "casp x0, x1, %[wdata64], %[wdata128], [%[loc]]\n"
200                 "casp x2, x3, %[wdata64], %[wdata128], [%[loc]]\n"
201                 "casp x4, x5, %[wdata64], %[wdata128], [%[loc]]\n"
202                 "casp x6, x7, %[wdata64], %[wdata128], [%[loc]]\n"
203                 "fmov d16, x0\n"
204                 "fmov v16.D[1], x1\n"
205                 "fmov d17, x2\n"
206                 "fmov v17.D[1], x3\n"
207                 "fmov d18, x4\n"
208                 "fmov v18.D[1], x5\n"
209                 "fmov d19, x6\n"
210                 "fmov v19.D[1], x7\n"
211                 "and %[failed].16B, %[failed].16B, v16.16B\n"
212                 "and %[failed].16B, %[failed].16B, v17.16B\n"
213                 "and %[failed].16B, %[failed].16B, v18.16B\n"
214                 "and %[failed].16B, %[failed].16B, v19.16B\n"
215                 "st1 { v16.2d, v17.2d, v18.2d, v19.2d}, [%[dst]], 64\n"
216                 : "+Q" (*addr), [failed] "=&w" (failed)
217                 : [wdata64] "r" (wdata64), [wdata128] "r" (wdata128),
218                 [dst] "r" (obj_table), [loc] "r" (addr)
219                 : "memory", "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
220                 "v16", "v17", "v18", "v19"
221                 );
222                 break;
223         }
224         case 4:
225         {
226                 asm volatile (
227                 ".cpu  generic+lse\n"
228                 "casp x0, x1, %[wdata64], %[wdata128], [%[loc]]\n"
229                 "casp x2, x3, %[wdata64], %[wdata128], [%[loc]]\n"
230                 "fmov d16, x0\n"
231                 "fmov v16.D[1], x1\n"
232                 "fmov d17, x2\n"
233                 "fmov v17.D[1], x3\n"
234                 "and %[failed].16B, %[failed].16B, v16.16B\n"
235                 "and %[failed].16B, %[failed].16B, v17.16B\n"
236                 "st1 { v16.2d, v17.2d}, [%[dst]], 32\n"
237                 : "+Q" (*addr), [failed] "=&w" (failed)
238                 : [wdata64] "r" (wdata64), [wdata128] "r" (wdata128),
239                 [dst] "r" (obj_table), [loc] "r" (addr)
240                 : "memory", "x0", "x1", "x2", "x3", "v16", "v17"
241                 );
242                 break;
243         }
244         case 2:
245         {
246                 asm volatile (
247                 ".cpu  generic+lse\n"
248                 "casp x0, x1, %[wdata64], %[wdata128], [%[loc]]\n"
249                 "fmov d16, x0\n"
250                 "fmov v16.D[1], x1\n"
251                 "and %[failed].16B, %[failed].16B, v16.16B\n"
252                 "st1 { v16.2d}, [%[dst]], 16\n"
253                 : "+Q" (*addr), [failed] "=&w" (failed)
254                 : [wdata64] "r" (wdata64), [wdata128] "r" (wdata128),
255                 [dst] "r" (obj_table), [loc] "r" (addr)
256                 : "memory", "x0", "x1", "v16"
257                 );
258                 break;
259         }
260         case 1:
261                 return npa_lf_aura_op_alloc_one(wdata, addr, obj_table, 0);
262         }
263
264         if (unlikely(!(vgetq_lane_u64(failed, 0) & vgetq_lane_u64(failed, 1))))
265                 return npa_lf_aura_op_search_alloc(wdata, addr, (void **)
266                         ((char *)obj_table - (sizeof(uint64_t) * n)), n);
267
268         return 0;
269 }
270
271 static __rte_noinline void
272 otx2_npa_clear_alloc(struct rte_mempool *mp, void **obj_table, unsigned int n)
273 {
274         unsigned int i;
275
276         for (i = 0; i < n; i++) {
277                 if (obj_table[i] != NULL) {
278                         otx2_npa_enq(mp, &obj_table[i], 1);
279                         obj_table[i] = NULL;
280                 }
281         }
282 }
283
284 static __rte_noinline int __hot
285 otx2_npa_deq_arm64(struct rte_mempool *mp, void **obj_table, unsigned int n)
286 {
287         const int64_t wdata = npa_lf_aura_handle_to_aura(mp->pool_id);
288         void **obj_table_bak = obj_table;
289         const unsigned int nfree = n;
290         unsigned int parts;
291
292         int64_t * const addr = (int64_t * const)
293                         (npa_lf_aura_handle_to_base(mp->pool_id) +
294                                 NPA_LF_AURA_OP_ALLOCX(0));
295         while (n) {
296                 parts = n > 31 ? 32 : rte_align32prevpow2(n);
297                 n -= parts;
298                 if (unlikely(npa_lf_aura_op_alloc_bulk(wdata, addr,
299                                 parts, obj_table))) {
300                         otx2_npa_clear_alloc(mp, obj_table_bak, nfree - n);
301                         return -ENOENT;
302                 }
303                 obj_table += parts;
304         }
305
306         return 0;
307 }
308
309 #else
310
311 static inline int __hot
312 otx2_npa_deq(struct rte_mempool *mp, void **obj_table, unsigned int n)
313 {
314         const int64_t wdata = npa_lf_aura_handle_to_aura(mp->pool_id);
315         unsigned int index;
316         uint64_t obj;
317
318         int64_t * const addr = (int64_t *)
319                         (npa_lf_aura_handle_to_base(mp->pool_id) +
320                                 NPA_LF_AURA_OP_ALLOCX(0));
321         for (index = 0; index < n; index++, obj_table++) {
322                 obj = npa_lf_aura_op_alloc_one(wdata, addr, obj_table, 0);
323                 if (obj == 0) {
324                         for (; index > 0; index--) {
325                                 obj_table--;
326                                 otx2_npa_enq(mp, obj_table, 1);
327                         }
328                         return -ENOENT;
329                 }
330                 *obj_table = (void *)obj;
331         }
332
333         return 0;
334 }
335
336 #endif
337
338 static unsigned int
339 otx2_npa_get_count(const struct rte_mempool *mp)
340 {
341         return (unsigned int)npa_lf_aura_op_available(mp->pool_id);
342 }
343
344 static int
345 npa_lf_aura_pool_init(struct otx2_mbox *mbox, uint32_t aura_id,
346                       struct npa_aura_s *aura, struct npa_pool_s *pool)
347 {
348         struct npa_aq_enq_req *aura_init_req, *pool_init_req;
349         struct npa_aq_enq_rsp *aura_init_rsp, *pool_init_rsp;
350         struct otx2_mbox_dev *mdev = &mbox->dev[0];
351         int rc, off;
352
353         aura_init_req = otx2_mbox_alloc_msg_npa_aq_enq(mbox);
354
355         aura_init_req->aura_id = aura_id;
356         aura_init_req->ctype = NPA_AQ_CTYPE_AURA;
357         aura_init_req->op = NPA_AQ_INSTOP_INIT;
358         otx2_mbox_memcpy(&aura_init_req->aura, aura, sizeof(*aura));
359
360         pool_init_req = otx2_mbox_alloc_msg_npa_aq_enq(mbox);
361
362         pool_init_req->aura_id = aura_id;
363         pool_init_req->ctype = NPA_AQ_CTYPE_POOL;
364         pool_init_req->op = NPA_AQ_INSTOP_INIT;
365         otx2_mbox_memcpy(&pool_init_req->pool, pool, sizeof(*pool));
366
367         otx2_mbox_msg_send(mbox, 0);
368         rc = otx2_mbox_wait_for_rsp(mbox, 0);
369         if (rc < 0)
370                 return rc;
371
372         off = mbox->rx_start +
373                         RTE_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
374         aura_init_rsp = (struct npa_aq_enq_rsp *)((uintptr_t)mdev->mbase + off);
375         off = mbox->rx_start + aura_init_rsp->hdr.next_msgoff;
376         pool_init_rsp = (struct npa_aq_enq_rsp *)((uintptr_t)mdev->mbase + off);
377
378         if (rc == 2 && aura_init_rsp->hdr.rc == 0 && pool_init_rsp->hdr.rc == 0)
379                 return 0;
380         else
381                 return NPA_LF_ERR_AURA_POOL_INIT;
382 }
383
384 static int
385 npa_lf_aura_pool_fini(struct otx2_mbox *mbox,
386                       uint32_t aura_id,
387                       uint64_t aura_handle)
388 {
389         struct npa_aq_enq_req *aura_req, *pool_req;
390         struct npa_aq_enq_rsp *aura_rsp, *pool_rsp;
391         struct otx2_mbox_dev *mdev = &mbox->dev[0];
392         struct ndc_sync_op *ndc_req;
393         int rc, off;
394
395         /* Procedure for disabling an aura/pool */
396         rte_delay_us(10);
397         npa_lf_aura_op_alloc(aura_handle, 0);
398
399         pool_req = otx2_mbox_alloc_msg_npa_aq_enq(mbox);
400         pool_req->aura_id = aura_id;
401         pool_req->ctype = NPA_AQ_CTYPE_POOL;
402         pool_req->op = NPA_AQ_INSTOP_WRITE;
403         pool_req->pool.ena = 0;
404         pool_req->pool_mask.ena = ~pool_req->pool_mask.ena;
405
406         aura_req = otx2_mbox_alloc_msg_npa_aq_enq(mbox);
407         aura_req->aura_id = aura_id;
408         aura_req->ctype = NPA_AQ_CTYPE_AURA;
409         aura_req->op = NPA_AQ_INSTOP_WRITE;
410         aura_req->aura.ena = 0;
411         aura_req->aura_mask.ena = ~aura_req->aura_mask.ena;
412
413         otx2_mbox_msg_send(mbox, 0);
414         rc = otx2_mbox_wait_for_rsp(mbox, 0);
415         if (rc < 0)
416                 return rc;
417
418         off = mbox->rx_start +
419                         RTE_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
420         pool_rsp = (struct npa_aq_enq_rsp *)((uintptr_t)mdev->mbase + off);
421
422         off = mbox->rx_start + pool_rsp->hdr.next_msgoff;
423         aura_rsp = (struct npa_aq_enq_rsp *)((uintptr_t)mdev->mbase + off);
424
425         if (rc != 2 || aura_rsp->hdr.rc != 0 || pool_rsp->hdr.rc != 0)
426                 return NPA_LF_ERR_AURA_POOL_FINI;
427
428         /* Sync NDC-NPA for LF */
429         ndc_req = otx2_mbox_alloc_msg_ndc_sync_op(mbox);
430         ndc_req->npa_lf_sync = 1;
431
432         rc = otx2_mbox_process(mbox);
433         if (rc) {
434                 otx2_err("Error on NDC-NPA LF sync, rc %d", rc);
435                 return NPA_LF_ERR_AURA_POOL_FINI;
436         }
437         return 0;
438 }
439
440 static inline char*
441 npa_lf_stack_memzone_name(struct otx2_npa_lf *lf, int pool_id, char *name)
442 {
443         snprintf(name, RTE_MEMZONE_NAMESIZE, "otx2_npa_stack_%x_%d",
444                         lf->pf_func, pool_id);
445
446         return name;
447 }
448
449 static inline const struct rte_memzone *
450 npa_lf_stack_dma_alloc(struct otx2_npa_lf *lf, char *name,
451                        int pool_id, size_t size)
452 {
453         return rte_memzone_reserve_aligned(
454                 npa_lf_stack_memzone_name(lf, pool_id, name), size, 0,
455                         RTE_MEMZONE_IOVA_CONTIG, OTX2_ALIGN);
456 }
457
458 static inline int
459 npa_lf_stack_dma_free(struct otx2_npa_lf *lf, char *name, int pool_id)
460 {
461         const struct rte_memzone *mz;
462
463         mz = rte_memzone_lookup(npa_lf_stack_memzone_name(lf, pool_id, name));
464         if (mz == NULL)
465                 return -EINVAL;
466
467         return rte_memzone_free(mz);
468 }
469
470 static inline int
471 bitmap_ctzll(uint64_t slab)
472 {
473         if (slab == 0)
474                 return 0;
475
476         return __builtin_ctzll(slab);
477 }
478
479 static int
480 npa_lf_aura_pool_pair_alloc(struct otx2_npa_lf *lf, const uint32_t block_size,
481                             const uint32_t block_count, struct npa_aura_s *aura,
482                             struct npa_pool_s *pool, uint64_t *aura_handle)
483 {
484         int rc, aura_id, pool_id, stack_size, alloc_size;
485         char name[RTE_MEMZONE_NAMESIZE];
486         const struct rte_memzone *mz;
487         uint64_t slab;
488         uint32_t pos;
489
490         /* Sanity check */
491         if (!lf || !block_size || !block_count ||
492             !pool || !aura || !aura_handle)
493                 return NPA_LF_ERR_PARAM;
494
495         /* Block size should be cache line aligned and in range of 128B-128KB */
496         if (block_size % OTX2_ALIGN || block_size < 128 ||
497             block_size > 128 * 1024)
498                 return NPA_LF_ERR_INVALID_BLOCK_SZ;
499
500         pos = slab = 0;
501         /* Scan from the beginning */
502         __rte_bitmap_scan_init(lf->npa_bmp);
503         /* Scan bitmap to get the free pool */
504         rc = rte_bitmap_scan(lf->npa_bmp, &pos, &slab);
505         /* Empty bitmap */
506         if (rc == 0) {
507                 otx2_err("Mempools exhausted, 'max_pools' devargs to increase");
508                 return -ERANGE;
509         }
510
511         /* Get aura_id from resource bitmap */
512         aura_id = pos + bitmap_ctzll(slab);
513         /* Mark pool as reserved */
514         rte_bitmap_clear(lf->npa_bmp, aura_id);
515
516         /* Configuration based on each aura has separate pool(aura-pool pair) */
517         pool_id = aura_id;
518         rc = (aura_id < 0 || pool_id >= (int)lf->nr_pools || aura_id >=
519               (int)BIT_ULL(6 + lf->aura_sz)) ? NPA_LF_ERR_AURA_ID_ALLOC : 0;
520         if (rc)
521                 goto exit;
522
523         /* Allocate stack memory */
524         stack_size = (block_count + lf->stack_pg_ptrs - 1) / lf->stack_pg_ptrs;
525         alloc_size = stack_size * lf->stack_pg_bytes;
526
527         mz = npa_lf_stack_dma_alloc(lf, name, pool_id, alloc_size);
528         if (mz == NULL) {
529                 rc = -ENOMEM;
530                 goto aura_res_put;
531         }
532
533         /* Update aura fields */
534         aura->pool_addr = pool_id;/* AF will translate to associated poolctx */
535         aura->ena = 1;
536         aura->shift = __builtin_clz(block_count) - 8;
537         aura->limit = block_count;
538         aura->pool_caching = 1;
539         aura->err_int_ena = BIT(NPA_AURA_ERR_INT_AURA_ADD_OVER);
540         aura->err_int_ena |= BIT(NPA_AURA_ERR_INT_AURA_ADD_UNDER);
541         aura->err_int_ena |= BIT(NPA_AURA_ERR_INT_AURA_FREE_UNDER);
542         aura->err_int_ena |= BIT(NPA_AURA_ERR_INT_POOL_DIS);
543         /* Many to one reduction */
544         aura->err_qint_idx = aura_id % lf->qints;
545
546         /* Update pool fields */
547         pool->stack_base = mz->iova;
548         pool->ena = 1;
549         pool->buf_size = block_size / OTX2_ALIGN;
550         pool->stack_max_pages = stack_size;
551         pool->shift = __builtin_clz(block_count) - 8;
552         pool->ptr_start = 0;
553         pool->ptr_end = ~0;
554         pool->stack_caching = 1;
555         pool->err_int_ena = BIT(NPA_POOL_ERR_INT_OVFLS);
556         pool->err_int_ena |= BIT(NPA_POOL_ERR_INT_RANGE);
557         pool->err_int_ena |= BIT(NPA_POOL_ERR_INT_PERR);
558
559         /* Many to one reduction */
560         pool->err_qint_idx = pool_id % lf->qints;
561
562         /* Issue AURA_INIT and POOL_INIT op */
563         rc = npa_lf_aura_pool_init(lf->mbox, aura_id, aura, pool);
564         if (rc)
565                 goto stack_mem_free;
566
567         *aura_handle = npa_lf_aura_handle_gen(aura_id, lf->base);
568
569         /* Update aura count */
570         npa_lf_aura_op_cnt_set(*aura_handle, 0, block_count);
571         /* Read it back to make sure aura count is updated */
572         npa_lf_aura_op_cnt_get(*aura_handle);
573
574         return 0;
575
576 stack_mem_free:
577         rte_memzone_free(mz);
578 aura_res_put:
579         rte_bitmap_set(lf->npa_bmp, aura_id);
580 exit:
581         return rc;
582 }
583
584 static int
585 npa_lf_aura_pool_pair_free(struct otx2_npa_lf *lf, uint64_t aura_handle)
586 {
587         char name[RTE_MEMZONE_NAMESIZE];
588         int aura_id, pool_id, rc;
589
590         if (!lf || !aura_handle)
591                 return NPA_LF_ERR_PARAM;
592
593         aura_id = pool_id = npa_lf_aura_handle_to_aura(aura_handle);
594         rc = npa_lf_aura_pool_fini(lf->mbox, aura_id, aura_handle);
595         rc |= npa_lf_stack_dma_free(lf, name, pool_id);
596
597         rte_bitmap_set(lf->npa_bmp, aura_id);
598
599         return rc;
600 }
601
602 static int
603 npa_lf_aura_range_update_check(uint64_t aura_handle)
604 {
605         uint64_t aura_id = npa_lf_aura_handle_to_aura(aura_handle);
606         struct otx2_npa_lf *lf = otx2_npa_lf_obj_get();
607         struct npa_aura_lim *lim = lf->aura_lim;
608         __otx2_io struct npa_pool_s *pool;
609         struct npa_aq_enq_req *req;
610         struct npa_aq_enq_rsp *rsp;
611         int rc;
612
613         req  = otx2_mbox_alloc_msg_npa_aq_enq(lf->mbox);
614
615         req->aura_id = aura_id;
616         req->ctype = NPA_AQ_CTYPE_POOL;
617         req->op = NPA_AQ_INSTOP_READ;
618
619         rc = otx2_mbox_process_msg(lf->mbox, (void *)&rsp);
620         if (rc) {
621                 otx2_err("Failed to get pool(0x%"PRIx64") context", aura_id);
622                 return rc;
623         }
624
625         pool = &rsp->pool;
626
627         if (lim[aura_id].ptr_start != pool->ptr_start ||
628                 lim[aura_id].ptr_end != pool->ptr_end) {
629                 otx2_err("Range update failed on pool(0x%"PRIx64")", aura_id);
630                 return -ERANGE;
631         }
632
633         return 0;
634 }
635
636 static int
637 otx2_npa_alloc(struct rte_mempool *mp)
638 {
639         uint32_t block_size, block_count;
640         struct otx2_npa_lf *lf;
641         struct npa_aura_s aura;
642         struct npa_pool_s pool;
643         uint64_t aura_handle;
644         int rc;
645
646         lf = otx2_npa_lf_obj_get();
647         if (lf == NULL) {
648                 rc = -EINVAL;
649                 goto error;
650         }
651
652         block_size = mp->elt_size + mp->header_size + mp->trailer_size;
653         block_count = mp->size;
654
655         if (block_size % OTX2_ALIGN != 0) {
656                 otx2_err("Block size should be multiple of 128B");
657                 rc = -ERANGE;
658                 goto error;
659         }
660
661         memset(&aura, 0, sizeof(struct npa_aura_s));
662         memset(&pool, 0, sizeof(struct npa_pool_s));
663         pool.nat_align = 1;
664         pool.buf_offset = 1;
665
666         if ((uint32_t)pool.buf_offset * OTX2_ALIGN != mp->header_size) {
667                 otx2_err("Unsupported mp->header_size=%d", mp->header_size);
668                 rc = -EINVAL;
669                 goto error;
670         }
671
672         /* Use driver specific mp->pool_config to override aura config */
673         if (mp->pool_config != NULL)
674                 memcpy(&aura, mp->pool_config, sizeof(struct npa_aura_s));
675
676         rc = npa_lf_aura_pool_pair_alloc(lf, block_size, block_count,
677                          &aura, &pool, &aura_handle);
678         if (rc) {
679                 otx2_err("Failed to alloc pool or aura rc=%d", rc);
680                 goto error;
681         }
682
683         /* Store aura_handle for future queue operations */
684         mp->pool_id = aura_handle;
685         otx2_npa_dbg("lf=%p block_sz=%d block_count=%d aura_handle=0x%"PRIx64,
686                      lf, block_size, block_count, aura_handle);
687
688         /* Just hold the reference of the object */
689         otx2_npa_lf_obj_ref();
690         return 0;
691 error:
692         return rc;
693 }
694
695 static void
696 otx2_npa_free(struct rte_mempool *mp)
697 {
698         struct otx2_npa_lf *lf = otx2_npa_lf_obj_get();
699         int rc = 0;
700
701         otx2_npa_dbg("lf=%p aura_handle=0x%"PRIx64, lf, mp->pool_id);
702         if (lf != NULL)
703                 rc = npa_lf_aura_pool_pair_free(lf, mp->pool_id);
704
705         if (rc)
706                 otx2_err("Failed to free pool or aura rc=%d", rc);
707
708         /* Release the reference of npalf */
709         otx2_npa_lf_fini();
710 }
711
712 static ssize_t
713 otx2_npa_calc_mem_size(const struct rte_mempool *mp, uint32_t obj_num,
714                        uint32_t pg_shift, size_t *min_chunk_size, size_t *align)
715 {
716         /*
717          * Simply need space for one more object to be able to
718          * fulfill alignment requirements.
719          */
720         return rte_mempool_op_calc_mem_size_helper(mp, obj_num + 1, pg_shift,
721                                                     min_chunk_size, align);
722 }
723
724 static int
725 otx2_npa_populate(struct rte_mempool *mp, unsigned int max_objs, void *vaddr,
726                   rte_iova_t iova, size_t len,
727                   rte_mempool_populate_obj_cb_t *obj_cb, void *obj_cb_arg)
728 {
729         size_t total_elt_sz;
730         size_t off;
731
732         if (iova == RTE_BAD_IOVA)
733                 return -EINVAL;
734
735         total_elt_sz = mp->header_size + mp->elt_size + mp->trailer_size;
736
737         /* Align object start address to a multiple of total_elt_sz */
738         off = total_elt_sz - ((uintptr_t)vaddr % total_elt_sz);
739
740         if (len < off)
741                 return -EINVAL;
742
743         vaddr = (char *)vaddr + off;
744         iova += off;
745         len -= off;
746
747         npa_lf_aura_op_range_set(mp->pool_id, iova, iova + len);
748
749         if (npa_lf_aura_range_update_check(mp->pool_id) < 0)
750                 return -EBUSY;
751
752         return rte_mempool_op_populate_helper(mp, max_objs, vaddr, iova, len,
753                                                obj_cb, obj_cb_arg);
754 }
755
756 static struct rte_mempool_ops otx2_npa_ops = {
757         .name = "octeontx2_npa",
758         .alloc = otx2_npa_alloc,
759         .free = otx2_npa_free,
760         .enqueue = otx2_npa_enq,
761         .get_count = otx2_npa_get_count,
762         .calc_mem_size = otx2_npa_calc_mem_size,
763         .populate = otx2_npa_populate,
764 #if defined(RTE_ARCH_ARM64)
765         .dequeue = otx2_npa_deq_arm64,
766 #else
767         .dequeue = otx2_npa_deq,
768 #endif
769 };
770
771 MEMPOOL_REGISTER_OPS(otx2_npa_ops);