New upstream version 17.11-rc3
[deb_dpdk.git] / drivers / mempool / dpaa / dpaa_mempool.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2017 NXP.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of NXP nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /* System headers */
34 #include <stdio.h>
35 #include <inttypes.h>
36 #include <unistd.h>
37 #include <limits.h>
38 #include <sched.h>
39 #include <signal.h>
40 #include <pthread.h>
41 #include <sys/types.h>
42 #include <sys/syscall.h>
43
44 #include <rte_byteorder.h>
45 #include <rte_common.h>
46 #include <rte_log.h>
47 #include <rte_debug.h>
48 #include <rte_memory.h>
49 #include <rte_tailq.h>
50 #include <rte_eal.h>
51 #include <rte_malloc.h>
52 #include <rte_ring.h>
53
54 #include <dpaa_mempool.h>
55
56 struct dpaa_bp_info rte_dpaa_bpid_info[DPAA_MAX_BPOOLS];
57
58 static int
59 dpaa_mbuf_create_pool(struct rte_mempool *mp)
60 {
61         struct bman_pool *bp;
62         struct bm_buffer bufs[8];
63         struct dpaa_bp_info *bp_info;
64         uint8_t bpid;
65         int num_bufs = 0, ret = 0;
66         struct bman_pool_params params = {
67                 .flags = BMAN_POOL_FLAG_DYNAMIC_BPID
68         };
69
70         MEMPOOL_INIT_FUNC_TRACE();
71
72         bp = bman_new_pool(&params);
73         if (!bp) {
74                 DPAA_MEMPOOL_ERR("bman_new_pool() failed");
75                 return -ENODEV;
76         }
77         bpid = bman_get_params(bp)->bpid;
78
79         /* Drain the pool of anything already in it. */
80         do {
81                 /* Acquire is all-or-nothing, so we drain in 8s,
82                  * then in 1s for the remainder.
83                  */
84                 if (ret != 1)
85                         ret = bman_acquire(bp, bufs, 8, 0);
86                 if (ret < 8)
87                         ret = bman_acquire(bp, bufs, 1, 0);
88                 if (ret > 0)
89                         num_bufs += ret;
90         } while (ret > 0);
91         if (num_bufs)
92                 DPAA_MEMPOOL_WARN("drained %u bufs from BPID %d",
93                                   num_bufs, bpid);
94
95         rte_dpaa_bpid_info[bpid].mp = mp;
96         rte_dpaa_bpid_info[bpid].bpid = bpid;
97         rte_dpaa_bpid_info[bpid].size = mp->elt_size;
98         rte_dpaa_bpid_info[bpid].bp = bp;
99         rte_dpaa_bpid_info[bpid].meta_data_size =
100                 sizeof(struct rte_mbuf) + rte_pktmbuf_priv_size(mp);
101         rte_dpaa_bpid_info[bpid].dpaa_ops_index = mp->ops_index;
102
103         bp_info = rte_malloc(NULL,
104                              sizeof(struct dpaa_bp_info),
105                              RTE_CACHE_LINE_SIZE);
106         if (!bp_info) {
107                 DPAA_MEMPOOL_WARN("Memory allocation failed for bp_info");
108                 bman_free_pool(bp);
109                 return -ENOMEM;
110         }
111
112         rte_memcpy(bp_info, (void *)&rte_dpaa_bpid_info[bpid],
113                    sizeof(struct dpaa_bp_info));
114         mp->pool_data = (void *)bp_info;
115
116         DPAA_MEMPOOL_INFO("BMAN pool created for bpid =%d", bpid);
117         return 0;
118 }
119
120 static void
121 dpaa_mbuf_free_pool(struct rte_mempool *mp)
122 {
123         struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp);
124
125         MEMPOOL_INIT_FUNC_TRACE();
126
127         if (bp_info) {
128                 bman_free_pool(bp_info->bp);
129                 DPAA_MEMPOOL_INFO("BMAN pool freed for bpid =%d",
130                                   bp_info->bpid);
131                 rte_free(mp->pool_data);
132                 mp->pool_data = NULL;
133         }
134 }
135
136 static void
137 dpaa_buf_free(struct dpaa_bp_info *bp_info, uint64_t addr)
138 {
139         struct bm_buffer buf;
140         int ret;
141
142         DPAA_MEMPOOL_DEBUG("Free 0x%lx to bpid: %d", addr, bp_info->bpid);
143
144         bm_buffer_set64(&buf, addr);
145 retry:
146         ret = bman_release(bp_info->bp, &buf, 1, 0);
147         if (ret) {
148                 DPAA_MEMPOOL_DEBUG("BMAN busy. Retrying...");
149                 cpu_spin(CPU_SPIN_BACKOFF_CYCLES);
150                 goto retry;
151         }
152 }
153
154 static int
155 dpaa_mbuf_free_bulk(struct rte_mempool *pool,
156                     void *const *obj_table,
157                     unsigned int n)
158 {
159         struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(pool);
160         int ret;
161         unsigned int i = 0;
162
163         DPAA_MEMPOOL_DPDEBUG("Request to free %d buffers in bpid = %d",
164                              n, bp_info->bpid);
165
166         ret = rte_dpaa_portal_init((void *)0);
167         if (ret) {
168                 DPAA_MEMPOOL_ERR("rte_dpaa_portal_init failed with ret: %d",
169                                  ret);
170                 return 0;
171         }
172
173         while (i < n) {
174                 dpaa_buf_free(bp_info,
175                               (uint64_t)rte_mempool_virt2iova(obj_table[i]) +
176                               bp_info->meta_data_size);
177                 i = i + 1;
178         }
179
180         DPAA_MEMPOOL_DPDEBUG("freed %d buffers in bpid =%d",
181                              n, bp_info->bpid);
182
183         return 0;
184 }
185
186 static int
187 dpaa_mbuf_alloc_bulk(struct rte_mempool *pool,
188                      void **obj_table,
189                      unsigned int count)
190 {
191         struct rte_mbuf **m = (struct rte_mbuf **)obj_table;
192         struct bm_buffer bufs[DPAA_MBUF_MAX_ACQ_REL];
193         struct dpaa_bp_info *bp_info;
194         void *bufaddr;
195         int i, ret;
196         unsigned int n = 0;
197
198         bp_info = DPAA_MEMPOOL_TO_POOL_INFO(pool);
199
200         DPAA_MEMPOOL_DPDEBUG("Request to alloc %d buffers in bpid = %d",
201                              count, bp_info->bpid);
202
203         if (unlikely(count >= (RTE_MEMPOOL_CACHE_MAX_SIZE * 2))) {
204                 DPAA_MEMPOOL_ERR("Unable to allocate requested (%u) buffers",
205                                  count);
206                 return -1;
207         }
208
209         ret = rte_dpaa_portal_init((void *)0);
210         if (ret) {
211                 DPAA_MEMPOOL_ERR("rte_dpaa_portal_init failed with ret: %d",
212                                  ret);
213                 return -1;
214         }
215
216         while (n < count) {
217                 /* Acquire is all-or-nothing, so we drain in 7s,
218                  * then the remainder.
219                  */
220                 if ((count - n) > DPAA_MBUF_MAX_ACQ_REL) {
221                         ret = bman_acquire(bp_info->bp, bufs,
222                                            DPAA_MBUF_MAX_ACQ_REL, 0);
223                 } else {
224                         ret = bman_acquire(bp_info->bp, bufs, count - n, 0);
225                 }
226                 /* In case of less than requested number of buffers available
227                  * in pool, qbman_swp_acquire returns 0
228                  */
229                 if (ret <= 0) {
230                         DPAA_MEMPOOL_DPDEBUG("Buffer acquire failed (%d)",
231                                              ret);
232                         /* The API expect the exact number of requested
233                          * buffers. Releasing all buffers allocated
234                          */
235                         dpaa_mbuf_free_bulk(pool, obj_table, n);
236                         return -ENOBUFS;
237                 }
238                 /* assigning mbuf from the acquired objects */
239                 for (i = 0; (i < ret) && bufs[i].addr; i++) {
240                         /* TODO-errata - objerved that bufs may be null
241                          * i.e. first buffer is valid, remaining 6 buffers
242                          * may be null.
243                          */
244                         bufaddr = (void *)rte_dpaa_mem_ptov(bufs[i].addr);
245                         m[n] = (struct rte_mbuf *)((char *)bufaddr
246                                                 - bp_info->meta_data_size);
247                         DPAA_MEMPOOL_DPDEBUG("Paddr (%p), FD (%p) from BMAN",
248                                              (void *)bufaddr, (void *)m[n]);
249                         n++;
250                 }
251         }
252
253         DPAA_MEMPOOL_DPDEBUG("Allocated %d buffers from bpid=%d",
254                              n, bp_info->bpid);
255         return 0;
256 }
257
258 static unsigned int
259 dpaa_mbuf_get_count(const struct rte_mempool *mp)
260 {
261         struct dpaa_bp_info *bp_info;
262
263         MEMPOOL_INIT_FUNC_TRACE();
264
265         if (!mp || !mp->pool_data) {
266                 DPAA_MEMPOOL_ERR("Invalid mempool provided\n");
267                 return 0;
268         }
269
270         bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp);
271
272         return bman_query_free_buffers(bp_info->bp);
273 }
274
275 struct rte_mempool_ops dpaa_mpool_ops = {
276         .name = "dpaa",
277         .alloc = dpaa_mbuf_create_pool,
278         .free = dpaa_mbuf_free_pool,
279         .enqueue = dpaa_mbuf_free_bulk,
280         .dequeue = dpaa_mbuf_alloc_bulk,
281         .get_count = dpaa_mbuf_get_count,
282 };
283
284 MEMPOOL_REGISTER_OPS(dpaa_mpool_ops);