drivers: use SPDX tag in NXP dpaa files
[dpdk.git] / drivers / mempool / dpaa / dpaa_mempool.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  *   Copyright 2017 NXP
4  *
5  */
6
7 /* System headers */
8 #include <stdio.h>
9 #include <inttypes.h>
10 #include <unistd.h>
11 #include <limits.h>
12 #include <sched.h>
13 #include <signal.h>
14 #include <pthread.h>
15 #include <sys/types.h>
16 #include <sys/syscall.h>
17
18 #include <rte_byteorder.h>
19 #include <rte_common.h>
20 #include <rte_log.h>
21 #include <rte_debug.h>
22 #include <rte_memory.h>
23 #include <rte_tailq.h>
24 #include <rte_eal.h>
25 #include <rte_malloc.h>
26 #include <rte_ring.h>
27
28 #include <dpaa_mempool.h>
29
30 struct dpaa_bp_info rte_dpaa_bpid_info[DPAA_MAX_BPOOLS];
31
32 static int
33 dpaa_mbuf_create_pool(struct rte_mempool *mp)
34 {
35         struct bman_pool *bp;
36         struct bm_buffer bufs[8];
37         struct dpaa_bp_info *bp_info;
38         uint8_t bpid;
39         int num_bufs = 0, ret = 0;
40         struct bman_pool_params params = {
41                 .flags = BMAN_POOL_FLAG_DYNAMIC_BPID
42         };
43
44         MEMPOOL_INIT_FUNC_TRACE();
45
46         bp = bman_new_pool(&params);
47         if (!bp) {
48                 DPAA_MEMPOOL_ERR("bman_new_pool() failed");
49                 return -ENODEV;
50         }
51         bpid = bman_get_params(bp)->bpid;
52
53         /* Drain the pool of anything already in it. */
54         do {
55                 /* Acquire is all-or-nothing, so we drain in 8s,
56                  * then in 1s for the remainder.
57                  */
58                 if (ret != 1)
59                         ret = bman_acquire(bp, bufs, 8, 0);
60                 if (ret < 8)
61                         ret = bman_acquire(bp, bufs, 1, 0);
62                 if (ret > 0)
63                         num_bufs += ret;
64         } while (ret > 0);
65         if (num_bufs)
66                 DPAA_MEMPOOL_WARN("drained %u bufs from BPID %d",
67                                   num_bufs, bpid);
68
69         rte_dpaa_bpid_info[bpid].mp = mp;
70         rte_dpaa_bpid_info[bpid].bpid = bpid;
71         rte_dpaa_bpid_info[bpid].size = mp->elt_size;
72         rte_dpaa_bpid_info[bpid].bp = bp;
73         rte_dpaa_bpid_info[bpid].meta_data_size =
74                 sizeof(struct rte_mbuf) + rte_pktmbuf_priv_size(mp);
75         rte_dpaa_bpid_info[bpid].dpaa_ops_index = mp->ops_index;
76
77         bp_info = rte_malloc(NULL,
78                              sizeof(struct dpaa_bp_info),
79                              RTE_CACHE_LINE_SIZE);
80         if (!bp_info) {
81                 DPAA_MEMPOOL_WARN("Memory allocation failed for bp_info");
82                 bman_free_pool(bp);
83                 return -ENOMEM;
84         }
85
86         rte_memcpy(bp_info, (void *)&rte_dpaa_bpid_info[bpid],
87                    sizeof(struct dpaa_bp_info));
88         mp->pool_data = (void *)bp_info;
89
90         DPAA_MEMPOOL_INFO("BMAN pool created for bpid =%d", bpid);
91         return 0;
92 }
93
94 static void
95 dpaa_mbuf_free_pool(struct rte_mempool *mp)
96 {
97         struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp);
98
99         MEMPOOL_INIT_FUNC_TRACE();
100
101         if (bp_info) {
102                 bman_free_pool(bp_info->bp);
103                 DPAA_MEMPOOL_INFO("BMAN pool freed for bpid =%d",
104                                   bp_info->bpid);
105                 rte_free(mp->pool_data);
106                 mp->pool_data = NULL;
107         }
108 }
109
110 static void
111 dpaa_buf_free(struct dpaa_bp_info *bp_info, uint64_t addr)
112 {
113         struct bm_buffer buf;
114         int ret;
115
116         DPAA_MEMPOOL_DEBUG("Free 0x%lx to bpid: %d", addr, bp_info->bpid);
117
118         bm_buffer_set64(&buf, addr);
119 retry:
120         ret = bman_release(bp_info->bp, &buf, 1, 0);
121         if (ret) {
122                 DPAA_MEMPOOL_DEBUG("BMAN busy. Retrying...");
123                 cpu_spin(CPU_SPIN_BACKOFF_CYCLES);
124                 goto retry;
125         }
126 }
127
128 static int
129 dpaa_mbuf_free_bulk(struct rte_mempool *pool,
130                     void *const *obj_table,
131                     unsigned int n)
132 {
133         struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(pool);
134         int ret;
135         unsigned int i = 0;
136
137         DPAA_MEMPOOL_DPDEBUG("Request to free %d buffers in bpid = %d",
138                              n, bp_info->bpid);
139
140         ret = rte_dpaa_portal_init((void *)0);
141         if (ret) {
142                 DPAA_MEMPOOL_ERR("rte_dpaa_portal_init failed with ret: %d",
143                                  ret);
144                 return 0;
145         }
146
147         while (i < n) {
148                 dpaa_buf_free(bp_info,
149                               (uint64_t)rte_mempool_virt2iova(obj_table[i]) +
150                               bp_info->meta_data_size);
151                 i = i + 1;
152         }
153
154         DPAA_MEMPOOL_DPDEBUG("freed %d buffers in bpid =%d",
155                              n, bp_info->bpid);
156
157         return 0;
158 }
159
160 static int
161 dpaa_mbuf_alloc_bulk(struct rte_mempool *pool,
162                      void **obj_table,
163                      unsigned int count)
164 {
165         struct rte_mbuf **m = (struct rte_mbuf **)obj_table;
166         struct bm_buffer bufs[DPAA_MBUF_MAX_ACQ_REL];
167         struct dpaa_bp_info *bp_info;
168         void *bufaddr;
169         int i, ret;
170         unsigned int n = 0;
171
172         bp_info = DPAA_MEMPOOL_TO_POOL_INFO(pool);
173
174         DPAA_MEMPOOL_DPDEBUG("Request to alloc %d buffers in bpid = %d",
175                              count, bp_info->bpid);
176
177         if (unlikely(count >= (RTE_MEMPOOL_CACHE_MAX_SIZE * 2))) {
178                 DPAA_MEMPOOL_ERR("Unable to allocate requested (%u) buffers",
179                                  count);
180                 return -1;
181         }
182
183         ret = rte_dpaa_portal_init((void *)0);
184         if (ret) {
185                 DPAA_MEMPOOL_ERR("rte_dpaa_portal_init failed with ret: %d",
186                                  ret);
187                 return -1;
188         }
189
190         while (n < count) {
191                 /* Acquire is all-or-nothing, so we drain in 7s,
192                  * then the remainder.
193                  */
194                 if ((count - n) > DPAA_MBUF_MAX_ACQ_REL) {
195                         ret = bman_acquire(bp_info->bp, bufs,
196                                            DPAA_MBUF_MAX_ACQ_REL, 0);
197                 } else {
198                         ret = bman_acquire(bp_info->bp, bufs, count - n, 0);
199                 }
200                 /* In case of less than requested number of buffers available
201                  * in pool, qbman_swp_acquire returns 0
202                  */
203                 if (ret <= 0) {
204                         DPAA_MEMPOOL_DPDEBUG("Buffer acquire failed (%d)",
205                                              ret);
206                         /* The API expect the exact number of requested
207                          * buffers. Releasing all buffers allocated
208                          */
209                         dpaa_mbuf_free_bulk(pool, obj_table, n);
210                         return -ENOBUFS;
211                 }
212                 /* assigning mbuf from the acquired objects */
213                 for (i = 0; (i < ret) && bufs[i].addr; i++) {
214                         /* TODO-errata - objerved that bufs may be null
215                          * i.e. first buffer is valid, remaining 6 buffers
216                          * may be null.
217                          */
218                         bufaddr = (void *)rte_dpaa_mem_ptov(bufs[i].addr);
219                         m[n] = (struct rte_mbuf *)((char *)bufaddr
220                                                 - bp_info->meta_data_size);
221                         DPAA_MEMPOOL_DPDEBUG("Paddr (%p), FD (%p) from BMAN",
222                                              (void *)bufaddr, (void *)m[n]);
223                         n++;
224                 }
225         }
226
227         DPAA_MEMPOOL_DPDEBUG("Allocated %d buffers from bpid=%d",
228                              n, bp_info->bpid);
229         return 0;
230 }
231
232 static unsigned int
233 dpaa_mbuf_get_count(const struct rte_mempool *mp)
234 {
235         struct dpaa_bp_info *bp_info;
236
237         MEMPOOL_INIT_FUNC_TRACE();
238
239         if (!mp || !mp->pool_data) {
240                 DPAA_MEMPOOL_ERR("Invalid mempool provided\n");
241                 return 0;
242         }
243
244         bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp);
245
246         return bman_query_free_buffers(bp_info->bp);
247 }
248
249 struct rte_mempool_ops dpaa_mpool_ops = {
250         .name = "dpaa",
251         .alloc = dpaa_mbuf_create_pool,
252         .free = dpaa_mbuf_free_pool,
253         .enqueue = dpaa_mbuf_free_bulk,
254         .dequeue = dpaa_mbuf_alloc_bulk,
255         .get_count = dpaa_mbuf_get_count,
256 };
257
258 MEMPOOL_REGISTER_OPS(dpaa_mpool_ops);