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 #include <dpaax_iova_table.h> 30 31 /* List of all the memseg information locally maintained in dpaa driver. This 32 * is to optimize the PA_to_VA searches until a better mechanism (algo) is 33 * available. 34 */ 35 struct dpaa_memseg_list rte_dpaa_memsegs 36 = TAILQ_HEAD_INITIALIZER(rte_dpaa_memsegs); 37 38 struct dpaa_bp_info *rte_dpaa_bpid_info; 39 40 static int 41 dpaa_mbuf_create_pool(struct rte_mempool *mp) 42 { 43 struct bman_pool *bp; 44 struct bm_buffer bufs[8]; 45 struct dpaa_bp_info *bp_info; 46 uint8_t bpid; 47 int num_bufs = 0, ret = 0; 48 struct bman_pool_params params = { 49 .flags = BMAN_POOL_FLAG_DYNAMIC_BPID 50 }; 51 52 MEMPOOL_INIT_FUNC_TRACE(); 53 54 bp = bman_new_pool(¶ms); 55 if (!bp) { 56 DPAA_MEMPOOL_ERR("bman_new_pool() failed"); 57 return -ENODEV; 58 } 59 bpid = bman_get_params(bp)->bpid; 60 61 /* Drain the pool of anything already in it. */ 62 do { 63 /* Acquire is all-or-nothing, so we drain in 8s, 64 * then in 1s for the remainder. 65 */ 66 if (ret != 1) 67 ret = bman_acquire(bp, bufs, 8, 0); 68 if (ret < 8) 69 ret = bman_acquire(bp, bufs, 1, 0); 70 if (ret > 0) 71 num_bufs += ret; 72 } while (ret > 0); 73 if (num_bufs) 74 DPAA_MEMPOOL_WARN("drained %u bufs from BPID %d", 75 num_bufs, bpid); 76 77 if (rte_dpaa_bpid_info == NULL) { 78 rte_dpaa_bpid_info = (struct dpaa_bp_info *)rte_zmalloc(NULL, 79 sizeof(struct dpaa_bp_info) * DPAA_MAX_BPOOLS, 80 RTE_CACHE_LINE_SIZE); 81 if (rte_dpaa_bpid_info == NULL) { 82 bman_free_pool(bp); 83 return -ENOMEM; 84 } 85 } 86 87 rte_dpaa_bpid_info[bpid].mp = mp; 88 rte_dpaa_bpid_info[bpid].bpid = bpid; 89 rte_dpaa_bpid_info[bpid].size = mp->elt_size; 90 rte_dpaa_bpid_info[bpid].bp = bp; 91 rte_dpaa_bpid_info[bpid].meta_data_size = 92 sizeof(struct rte_mbuf) + rte_pktmbuf_priv_size(mp); 93 rte_dpaa_bpid_info[bpid].dpaa_ops_index = mp->ops_index; 94 rte_dpaa_bpid_info[bpid].ptov_off = 0; 95 rte_dpaa_bpid_info[bpid].flags = 0; 96 97 bp_info = rte_malloc(NULL, 98 sizeof(struct dpaa_bp_info), 99 RTE_CACHE_LINE_SIZE); 100 if (!bp_info) { 101 DPAA_MEMPOOL_WARN("Memory allocation failed for bp_info"); 102 bman_free_pool(bp); 103 return -ENOMEM; 104 } 105 106 rte_memcpy(bp_info, (void *)&rte_dpaa_bpid_info[bpid], 107 sizeof(struct dpaa_bp_info)); 108 mp->pool_data = (void *)bp_info; 109 110 DPAA_MEMPOOL_INFO("BMAN pool created for bpid =%d", bpid); 111 return 0; 112 } 113 114 static void 115 dpaa_mbuf_free_pool(struct rte_mempool *mp) 116 { 117 struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp); 118 119 MEMPOOL_INIT_FUNC_TRACE(); 120 121 if (bp_info) { 122 bman_free_pool(bp_info->bp); 123 DPAA_MEMPOOL_INFO("BMAN pool freed for bpid =%d", 124 bp_info->bpid); 125 rte_free(mp->pool_data); 126 mp->pool_data = NULL; 127 } 128 } 129 130 static void 131 dpaa_buf_free(struct dpaa_bp_info *bp_info, uint64_t addr) 132 { 133 struct bm_buffer buf; 134 int ret; 135 136 DPAA_MEMPOOL_DPDEBUG("Free 0x%" PRIx64 " to bpid: %d", 137 addr, bp_info->bpid); 138 139 bm_buffer_set64(&buf, addr); 140 retry: 141 ret = bman_release(bp_info->bp, &buf, 1, 0); 142 if (ret) { 143 DPAA_MEMPOOL_DEBUG("BMAN busy. Retrying..."); 144 cpu_spin(CPU_SPIN_BACKOFF_CYCLES); 145 goto retry; 146 } 147 } 148 149 static int 150 dpaa_mbuf_free_bulk(struct rte_mempool *pool, 151 void *const *obj_table, 152 unsigned int n) 153 { 154 struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(pool); 155 int ret; 156 unsigned int i = 0; 157 158 DPAA_MEMPOOL_DPDEBUG("Request to free %d buffers in bpid = %d", 159 n, bp_info->bpid); 160 161 if (unlikely(!RTE_PER_LCORE(dpaa_io))) { 162 ret = rte_dpaa_portal_init((void *)0); 163 if (ret) { 164 DPAA_MEMPOOL_ERR("rte_dpaa_portal_init failed with ret: %d", 165 ret); 166 return 0; 167 } 168 } 169 170 while (i < n) { 171 uint64_t phy = rte_mempool_virt2iova(obj_table[i]); 172 173 if (unlikely(!bp_info->ptov_off)) { 174 /* buffers are from single mem segment */ 175 if (bp_info->flags & DPAA_MPOOL_SINGLE_SEGMENT) { 176 bp_info->ptov_off = (size_t)obj_table[i] - phy; 177 rte_dpaa_bpid_info[bp_info->bpid].ptov_off 178 = bp_info->ptov_off; 179 } 180 } 181 182 dpaa_buf_free(bp_info, 183 (uint64_t)phy + bp_info->meta_data_size); 184 i = i + 1; 185 } 186 187 DPAA_MEMPOOL_DPDEBUG("freed %d buffers in bpid =%d", 188 n, bp_info->bpid); 189 190 return 0; 191 } 192 193 static int 194 dpaa_mbuf_alloc_bulk(struct rte_mempool *pool, 195 void **obj_table, 196 unsigned int count) 197 { 198 struct rte_mbuf **m = (struct rte_mbuf **)obj_table; 199 struct bm_buffer bufs[DPAA_MBUF_MAX_ACQ_REL]; 200 struct dpaa_bp_info *bp_info; 201 void *bufaddr; 202 int i, ret; 203 unsigned int n = 0; 204 205 bp_info = DPAA_MEMPOOL_TO_POOL_INFO(pool); 206 207 DPAA_MEMPOOL_DPDEBUG("Request to alloc %d buffers in bpid = %d", 208 count, bp_info->bpid); 209 210 if (unlikely(count >= (RTE_MEMPOOL_CACHE_MAX_SIZE * 2))) { 211 DPAA_MEMPOOL_ERR("Unable to allocate requested (%u) buffers", 212 count); 213 return -1; 214 } 215 216 if (unlikely(!RTE_PER_LCORE(dpaa_io))) { 217 ret = rte_dpaa_portal_init((void *)0); 218 if (ret) { 219 DPAA_MEMPOOL_ERR("rte_dpaa_portal_init failed with ret: %d", 220 ret); 221 return -1; 222 } 223 } 224 225 while (n < count) { 226 /* Acquire is all-or-nothing, so we drain in 7s, 227 * then the remainder. 228 */ 229 if ((count - n) > DPAA_MBUF_MAX_ACQ_REL) { 230 ret = bman_acquire(bp_info->bp, bufs, 231 DPAA_MBUF_MAX_ACQ_REL, 0); 232 } else { 233 ret = bman_acquire(bp_info->bp, bufs, count - n, 0); 234 } 235 /* In case of less than requested number of buffers available 236 * in pool, qbman_swp_acquire returns 0 237 */ 238 if (ret <= 0) { 239 DPAA_MEMPOOL_DPDEBUG("Buffer acquire failed (%d)", 240 ret); 241 /* The API expect the exact number of requested 242 * buffers. Releasing all buffers allocated 243 */ 244 dpaa_mbuf_free_bulk(pool, obj_table, n); 245 return -ENOBUFS; 246 } 247 /* assigning mbuf from the acquired objects */ 248 for (i = 0; (i < ret) && bufs[i].addr; i++) { 249 /* TODO-errata - objerved that bufs may be null 250 * i.e. first buffer is valid, remaining 6 buffers 251 * may be null. 252 */ 253 bufaddr = DPAA_MEMPOOL_PTOV(bp_info, bufs[i].addr); 254 m[n] = (struct rte_mbuf *)((char *)bufaddr 255 - bp_info->meta_data_size); 256 DPAA_MEMPOOL_DPDEBUG("Paddr (%p), FD (%p) from BMAN", 257 (void *)bufaddr, (void *)m[n]); 258 n++; 259 } 260 } 261 262 DPAA_MEMPOOL_DPDEBUG("Allocated %d buffers from bpid=%d", 263 n, bp_info->bpid); 264 return 0; 265 } 266 267 static unsigned int 268 dpaa_mbuf_get_count(const struct rte_mempool *mp) 269 { 270 struct dpaa_bp_info *bp_info; 271 272 MEMPOOL_INIT_FUNC_TRACE(); 273 274 if (!mp || !mp->pool_data) { 275 DPAA_MEMPOOL_ERR("Invalid mempool provided\n"); 276 return 0; 277 } 278 279 bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp); 280 281 return bman_query_free_buffers(bp_info->bp); 282 } 283 284 static int 285 dpaa_populate(struct rte_mempool *mp, unsigned int max_objs, 286 void *vaddr, rte_iova_t paddr, size_t len, 287 rte_mempool_populate_obj_cb_t *obj_cb, void *obj_cb_arg) 288 { 289 struct dpaa_bp_info *bp_info; 290 unsigned int total_elt_sz; 291 292 MEMPOOL_INIT_FUNC_TRACE(); 293 294 if (!mp || !mp->pool_data) { 295 DPAA_MEMPOOL_ERR("Invalid mempool provided\n"); 296 return 0; 297 } 298 299 /* Update the PA-VA Table */ 300 dpaax_iova_table_update(paddr, vaddr, len); 301 302 bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp); 303 total_elt_sz = mp->header_size + mp->elt_size + mp->trailer_size; 304 305 DPAA_MEMPOOL_DEBUG("Req size %" PRIx64 " vs Available %u\n", 306 (uint64_t)len, total_elt_sz * mp->size); 307 308 /* Detect pool area has sufficient space for elements in this memzone */ 309 if (len >= total_elt_sz * mp->size) 310 bp_info->flags |= DPAA_MPOOL_SINGLE_SEGMENT; 311 struct dpaa_memseg *ms; 312 313 /* For each memory chunk pinned to the Mempool, a linked list of the 314 * contained memsegs is created for searching when PA to VA 315 * conversion is required. 316 */ 317 ms = rte_zmalloc(NULL, sizeof(struct dpaa_memseg), 0); 318 if (!ms) { 319 DPAA_MEMPOOL_ERR("Unable to allocate internal memory."); 320 DPAA_MEMPOOL_WARN("Fast Physical to Virtual Addr translation would not be available."); 321 /* If the element is not added, it would only lead to failure 322 * in searching for the element and the logic would Fallback 323 * to traditional DPDK memseg traversal code. So, this is not 324 * a blocking error - but, error would be printed on screen. 325 */ 326 return 0; 327 } 328 329 ms->vaddr = vaddr; 330 ms->iova = paddr; 331 ms->len = len; 332 /* Head insertions are generally faster than tail insertions as the 333 * buffers pinned are picked from rear end. 334 */ 335 TAILQ_INSERT_HEAD(&rte_dpaa_memsegs, ms, next); 336 337 return rte_mempool_op_populate_default(mp, max_objs, vaddr, paddr, len, 338 obj_cb, obj_cb_arg); 339 } 340 341 static const struct rte_mempool_ops dpaa_mpool_ops = { 342 .name = DPAA_MEMPOOL_OPS_NAME, 343 .alloc = dpaa_mbuf_create_pool, 344 .free = dpaa_mbuf_free_pool, 345 .enqueue = dpaa_mbuf_free_bulk, 346 .dequeue = dpaa_mbuf_alloc_bulk, 347 .get_count = dpaa_mbuf_get_count, 348 .populate = dpaa_populate, 349 }; 350 351 MEMPOOL_REGISTER_OPS(dpaa_mpool_ops); 352