1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. 4 * Copyright 2016 NXP 5 * 6 */ 7 8 #include <unistd.h> 9 #include <stdio.h> 10 #include <sys/types.h> 11 #include <string.h> 12 #include <stdlib.h> 13 #include <fcntl.h> 14 #include <errno.h> 15 16 #include <rte_mbuf.h> 17 #include <rte_ethdev_driver.h> 18 #include <rte_malloc.h> 19 #include <rte_memcpy.h> 20 #include <rte_string_fns.h> 21 #include <rte_cycles.h> 22 #include <rte_kvargs.h> 23 #include <rte_dev.h> 24 #include "rte_dpaa2_mempool.h" 25 26 #include <fslmc_logs.h> 27 #include <mc/fsl_dpbp.h> 28 #include <portal/dpaa2_hw_pvt.h> 29 #include <portal/dpaa2_hw_dpio.h> 30 #include "dpaa2_hw_mempool.h" 31 #include "dpaa2_hw_mempool_logs.h" 32 33 #include <dpaax_iova_table.h> 34 35 struct dpaa2_bp_info rte_dpaa2_bpid_info[MAX_BPID]; 36 static struct dpaa2_bp_list *h_bp_list; 37 38 /* Dynamic logging identified for mempool */ 39 int dpaa2_logtype_mempool; 40 41 static int 42 rte_hw_mbuf_create_pool(struct rte_mempool *mp) 43 { 44 struct dpaa2_bp_list *bp_list; 45 struct dpaa2_dpbp_dev *avail_dpbp; 46 struct dpaa2_bp_info *bp_info; 47 struct dpbp_attr dpbp_attr; 48 uint32_t bpid; 49 int ret; 50 51 avail_dpbp = dpaa2_alloc_dpbp_dev(); 52 53 if (!avail_dpbp) { 54 DPAA2_MEMPOOL_ERR("DPAA2 pool not available!"); 55 return -ENOENT; 56 } 57 58 if (unlikely(!DPAA2_PER_LCORE_DPIO)) { 59 ret = dpaa2_affine_qbman_swp(); 60 if (ret) { 61 DPAA2_MEMPOOL_ERR("Failure in affining portal"); 62 goto err1; 63 } 64 } 65 66 ret = dpbp_enable(&avail_dpbp->dpbp, CMD_PRI_LOW, avail_dpbp->token); 67 if (ret != 0) { 68 DPAA2_MEMPOOL_ERR("Resource enable failure with err code: %d", 69 ret); 70 goto err1; 71 } 72 73 ret = dpbp_get_attributes(&avail_dpbp->dpbp, CMD_PRI_LOW, 74 avail_dpbp->token, &dpbp_attr); 75 if (ret != 0) { 76 DPAA2_MEMPOOL_ERR("Resource read failure with err code: %d", 77 ret); 78 goto err2; 79 } 80 81 bp_info = rte_malloc(NULL, 82 sizeof(struct dpaa2_bp_info), 83 RTE_CACHE_LINE_SIZE); 84 if (!bp_info) { 85 DPAA2_MEMPOOL_ERR("Unable to allocate buffer pool memory"); 86 ret = -ENOMEM; 87 goto err2; 88 } 89 90 /* Allocate the bp_list which will be added into global_bp_list */ 91 bp_list = rte_malloc(NULL, sizeof(struct dpaa2_bp_list), 92 RTE_CACHE_LINE_SIZE); 93 if (!bp_list) { 94 DPAA2_MEMPOOL_ERR("Unable to allocate buffer pool memory"); 95 ret = -ENOMEM; 96 goto err3; 97 } 98 99 /* Set parameters of buffer pool list */ 100 bp_list->buf_pool.num_bufs = mp->size; 101 bp_list->buf_pool.size = mp->elt_size 102 - sizeof(struct rte_mbuf) - rte_pktmbuf_priv_size(mp); 103 bp_list->buf_pool.bpid = dpbp_attr.bpid; 104 bp_list->buf_pool.h_bpool_mem = NULL; 105 bp_list->buf_pool.dpbp_node = avail_dpbp; 106 /* Identification for our offloaded pool_data structure */ 107 bp_list->dpaa2_ops_index = mp->ops_index; 108 bp_list->next = h_bp_list; 109 bp_list->mp = mp; 110 111 bpid = dpbp_attr.bpid; 112 113 rte_dpaa2_bpid_info[bpid].meta_data_size = sizeof(struct rte_mbuf) 114 + rte_pktmbuf_priv_size(mp); 115 rte_dpaa2_bpid_info[bpid].bp_list = bp_list; 116 rte_dpaa2_bpid_info[bpid].bpid = bpid; 117 118 rte_memcpy(bp_info, (void *)&rte_dpaa2_bpid_info[bpid], 119 sizeof(struct dpaa2_bp_info)); 120 mp->pool_data = (void *)bp_info; 121 122 DPAA2_MEMPOOL_DEBUG("BP List created for bpid =%d", dpbp_attr.bpid); 123 124 h_bp_list = bp_list; 125 return 0; 126 err3: 127 rte_free(bp_info); 128 err2: 129 dpbp_disable(&avail_dpbp->dpbp, CMD_PRI_LOW, avail_dpbp->token); 130 err1: 131 dpaa2_free_dpbp_dev(avail_dpbp); 132 133 return ret; 134 } 135 136 static void 137 rte_hw_mbuf_free_pool(struct rte_mempool *mp) 138 { 139 struct dpaa2_bp_info *bpinfo; 140 struct dpaa2_bp_list *bp; 141 struct dpaa2_dpbp_dev *dpbp_node; 142 143 if (!mp->pool_data) { 144 DPAA2_MEMPOOL_ERR("Not a valid dpaa2 buffer pool"); 145 return; 146 } 147 148 bpinfo = (struct dpaa2_bp_info *)mp->pool_data; 149 bp = bpinfo->bp_list; 150 dpbp_node = bp->buf_pool.dpbp_node; 151 152 dpbp_disable(&(dpbp_node->dpbp), CMD_PRI_LOW, dpbp_node->token); 153 154 if (h_bp_list == bp) { 155 h_bp_list = h_bp_list->next; 156 } else { /* if it is not the first node */ 157 struct dpaa2_bp_list *prev = h_bp_list, *temp; 158 temp = h_bp_list->next; 159 while (temp) { 160 if (temp == bp) { 161 prev->next = temp->next; 162 rte_free(bp); 163 break; 164 } 165 prev = temp; 166 temp = temp->next; 167 } 168 } 169 170 rte_free(mp->pool_data); 171 dpaa2_free_dpbp_dev(dpbp_node); 172 } 173 174 static void 175 rte_dpaa2_mbuf_release(struct rte_mempool *pool __rte_unused, 176 void * const *obj_table, 177 uint32_t bpid, 178 uint32_t meta_data_size, 179 int count) 180 { 181 struct qbman_release_desc releasedesc; 182 struct qbman_swp *swp; 183 int ret; 184 int i, n; 185 uint64_t bufs[DPAA2_MBUF_MAX_ACQ_REL]; 186 187 if (unlikely(!DPAA2_PER_LCORE_DPIO)) { 188 ret = dpaa2_affine_qbman_swp(); 189 if (ret != 0) { 190 DPAA2_MEMPOOL_ERR("Failed to allocate IO portal"); 191 return; 192 } 193 } 194 swp = DPAA2_PER_LCORE_PORTAL; 195 196 /* Create a release descriptor required for releasing 197 * buffers into QBMAN 198 */ 199 qbman_release_desc_clear(&releasedesc); 200 qbman_release_desc_set_bpid(&releasedesc, bpid); 201 202 n = count % DPAA2_MBUF_MAX_ACQ_REL; 203 if (unlikely(!n)) 204 goto aligned; 205 206 /* convert mbuf to buffers for the remainder */ 207 for (i = 0; i < n ; i++) { 208 #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA 209 bufs[i] = (uint64_t)rte_mempool_virt2iova(obj_table[i]) 210 + meta_data_size; 211 #else 212 bufs[i] = (uint64_t)obj_table[i] + meta_data_size; 213 #endif 214 } 215 216 /* feed them to bman */ 217 do { 218 ret = qbman_swp_release(swp, &releasedesc, bufs, n); 219 } while (ret == -EBUSY); 220 221 aligned: 222 /* if there are more buffers to free */ 223 while (n < count) { 224 /* convert mbuf to buffers */ 225 for (i = 0; i < DPAA2_MBUF_MAX_ACQ_REL; i++) { 226 #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA 227 bufs[i] = (uint64_t) 228 rte_mempool_virt2iova(obj_table[n + i]) 229 + meta_data_size; 230 #else 231 bufs[i] = (uint64_t)obj_table[n + i] + meta_data_size; 232 #endif 233 } 234 235 do { 236 ret = qbman_swp_release(swp, &releasedesc, bufs, 237 DPAA2_MBUF_MAX_ACQ_REL); 238 } while (ret == -EBUSY); 239 n += DPAA2_MBUF_MAX_ACQ_REL; 240 } 241 } 242 243 uint16_t 244 rte_dpaa2_mbuf_pool_bpid(struct rte_mempool *mp) 245 { 246 struct dpaa2_bp_info *bp_info; 247 248 bp_info = mempool_to_bpinfo(mp); 249 if (!(bp_info->bp_list)) { 250 RTE_LOG(ERR, PMD, "DPAA2 buffer pool not configured\n"); 251 return -ENOMEM; 252 } 253 254 return bp_info->bpid; 255 } 256 257 struct rte_mbuf * 258 rte_dpaa2_mbuf_from_buf_addr(struct rte_mempool *mp, void *buf_addr) 259 { 260 struct dpaa2_bp_info *bp_info; 261 262 bp_info = mempool_to_bpinfo(mp); 263 if (!(bp_info->bp_list)) { 264 RTE_LOG(ERR, PMD, "DPAA2 buffer pool not configured\n"); 265 return NULL; 266 } 267 268 return (struct rte_mbuf *)((uint8_t *)buf_addr - 269 bp_info->meta_data_size); 270 } 271 272 int 273 rte_dpaa2_mbuf_alloc_bulk(struct rte_mempool *pool, 274 void **obj_table, unsigned int count) 275 { 276 #ifdef RTE_LIBRTE_DPAA2_DEBUG_DRIVER 277 static int alloc; 278 #endif 279 struct qbman_swp *swp; 280 uint16_t bpid; 281 size_t bufs[DPAA2_MBUF_MAX_ACQ_REL]; 282 int i, ret; 283 unsigned int n = 0; 284 struct dpaa2_bp_info *bp_info; 285 286 bp_info = mempool_to_bpinfo(pool); 287 288 if (!(bp_info->bp_list)) { 289 DPAA2_MEMPOOL_ERR("DPAA2 buffer pool not configured"); 290 return -ENOENT; 291 } 292 293 bpid = bp_info->bpid; 294 295 if (unlikely(!DPAA2_PER_LCORE_DPIO)) { 296 ret = dpaa2_affine_qbman_swp(); 297 if (ret != 0) { 298 DPAA2_MEMPOOL_ERR("Failed to allocate IO portal"); 299 return ret; 300 } 301 } 302 swp = DPAA2_PER_LCORE_PORTAL; 303 304 while (n < count) { 305 /* Acquire is all-or-nothing, so we drain in 7s, 306 * then the remainder. 307 */ 308 if ((count - n) > DPAA2_MBUF_MAX_ACQ_REL) { 309 ret = qbman_swp_acquire(swp, bpid, (void *)bufs, 310 DPAA2_MBUF_MAX_ACQ_REL); 311 } else { 312 ret = qbman_swp_acquire(swp, bpid, (void *)bufs, 313 count - n); 314 } 315 /* In case of less than requested number of buffers available 316 * in pool, qbman_swp_acquire returns 0 317 */ 318 if (ret <= 0) { 319 DPAA2_MEMPOOL_DP_DEBUG( 320 "Buffer acquire failed with err code: %d", ret); 321 /* The API expect the exact number of requested bufs */ 322 /* Releasing all buffers allocated */ 323 rte_dpaa2_mbuf_release(pool, obj_table, bpid, 324 bp_info->meta_data_size, n); 325 return -ENOBUFS; 326 } 327 /* assigning mbuf from the acquired objects */ 328 for (i = 0; (i < ret) && bufs[i]; i++) { 329 DPAA2_MODIFY_IOVA_TO_VADDR(bufs[i], size_t); 330 obj_table[n] = (struct rte_mbuf *) 331 (bufs[i] - bp_info->meta_data_size); 332 DPAA2_MEMPOOL_DP_DEBUG( 333 "Acquired %p address %p from BMAN\n", 334 (void *)bufs[i], (void *)obj_table[n]); 335 n++; 336 } 337 } 338 339 #ifdef RTE_LIBRTE_DPAA2_DEBUG_DRIVER 340 alloc += n; 341 DPAA2_MEMPOOL_DP_DEBUG("Total = %d , req = %d done = %d\n", 342 alloc, count, n); 343 #endif 344 return 0; 345 } 346 347 static int 348 rte_hw_mbuf_free_bulk(struct rte_mempool *pool, 349 void * const *obj_table, unsigned int n) 350 { 351 struct dpaa2_bp_info *bp_info; 352 353 bp_info = mempool_to_bpinfo(pool); 354 if (!(bp_info->bp_list)) { 355 DPAA2_MEMPOOL_ERR("DPAA2 buffer pool not configured"); 356 return -ENOENT; 357 } 358 rte_dpaa2_mbuf_release(pool, obj_table, bp_info->bpid, 359 bp_info->meta_data_size, n); 360 361 return 0; 362 } 363 364 static unsigned int 365 rte_hw_mbuf_get_count(const struct rte_mempool *mp) 366 { 367 int ret; 368 unsigned int num_of_bufs = 0; 369 struct dpaa2_bp_info *bp_info; 370 struct dpaa2_dpbp_dev *dpbp_node; 371 372 if (!mp || !mp->pool_data) { 373 DPAA2_MEMPOOL_ERR("Invalid mempool provided"); 374 return 0; 375 } 376 377 bp_info = (struct dpaa2_bp_info *)mp->pool_data; 378 dpbp_node = bp_info->bp_list->buf_pool.dpbp_node; 379 380 ret = dpbp_get_num_free_bufs(&dpbp_node->dpbp, CMD_PRI_LOW, 381 dpbp_node->token, &num_of_bufs); 382 if (ret) { 383 DPAA2_MEMPOOL_ERR("Unable to obtain free buf count (err=%d)", 384 ret); 385 return 0; 386 } 387 388 DPAA2_MEMPOOL_DP_DEBUG("Free bufs = %u\n", num_of_bufs); 389 390 return num_of_bufs; 391 } 392 393 static int 394 dpaa2_populate(struct rte_mempool *mp, unsigned int max_objs, 395 void *vaddr, rte_iova_t paddr, size_t len, 396 rte_mempool_populate_obj_cb_t *obj_cb, void *obj_cb_arg) 397 { 398 /* Insert entry into the PA->VA Table */ 399 dpaax_iova_table_update(paddr, vaddr, len); 400 401 return rte_mempool_op_populate_default(mp, max_objs, vaddr, paddr, len, 402 obj_cb, obj_cb_arg); 403 } 404 405 static const struct rte_mempool_ops dpaa2_mpool_ops = { 406 .name = DPAA2_MEMPOOL_OPS_NAME, 407 .alloc = rte_hw_mbuf_create_pool, 408 .free = rte_hw_mbuf_free_pool, 409 .enqueue = rte_hw_mbuf_free_bulk, 410 .dequeue = rte_dpaa2_mbuf_alloc_bulk, 411 .get_count = rte_hw_mbuf_get_count, 412 .populate = dpaa2_populate, 413 }; 414 415 MEMPOOL_REGISTER_OPS(dpaa2_mpool_ops); 416 417 RTE_INIT(dpaa2_mempool_init_log) 418 { 419 dpaa2_logtype_mempool = rte_log_register("mempool.dpaa2"); 420 if (dpaa2_logtype_mempool >= 0) 421 rte_log_set_level(dpaa2_logtype_mempool, RTE_LOG_NOTICE); 422 } 423