| 446 | } |
| 447 | |
| 448 | static void |
| 449 | _mlx5_ipool_free_cache(struct mlx5_indexed_pool *pool, int cidx, uint32_t idx) |
| 450 | { |
| 451 | struct mlx5_ipool_per_lcore *ilc; |
| 452 | struct mlx5_indexed_cache *gc, *olc = NULL; |
| 453 | uint32_t reclaim_num = 0; |
| 454 | |
| 455 | MLX5_ASSERT(idx); |
| 456 | /* |
| 457 | * When index was allocated on core A but freed on core B. In this |
| 458 | * case check if local cache on core B was allocated before. |
| 459 | */ |
| 460 | if (unlikely(!pool->cache[cidx])) { |
| 461 | pool->cache[cidx] = pool->cfg.malloc(MLX5_MEM_ZERO, |
| 462 | sizeof(struct mlx5_ipool_per_lcore) + |
| 463 | (pool->cfg.per_core_cache * sizeof(uint32_t)), |
| 464 | RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); |
| 465 | if (!pool->cache[cidx]) { |
| 466 | DRV_LOG(ERR, "Ipool cache%d allocate failed\n", cidx); |
| 467 | return; |
| 468 | } |
| 469 | } |
| 470 | /* Try to enqueue to local index cache. */ |
| 471 | if (pool->cache[cidx]->len < pool->cfg.per_core_cache) { |
| 472 | pool->cache[cidx]->idx[pool->cache[cidx]->len] = idx; |
| 473 | pool->cache[cidx]->len++; |
| 474 | return; |
| 475 | } |
| 476 | ilc = pool->cache[cidx]; |
| 477 | reclaim_num = pool->cfg.per_core_cache >> 2; |
| 478 | ilc->len -= reclaim_num; |
| 479 | /* Local index cache full, try with global index cache. */ |
| 480 | mlx5_ipool_lock(pool); |
| 481 | gc = pool->gc; |
| 482 | if (ilc->lc != gc) { |
| 483 | if (ilc->lc && !(--ilc->lc->ref_cnt)) |
| 484 | olc = ilc->lc; |
| 485 | gc->ref_cnt++; |
| 486 | ilc->lc = gc; |
| 487 | } |
| 488 | memcpy(&gc->idx[gc->len], &ilc->idx[ilc->len], |
| 489 | reclaim_num * sizeof(uint32_t)); |
| 490 | gc->len += reclaim_num; |
| 491 | mlx5_ipool_unlock(pool); |
| 492 | if (olc) |
| 493 | pool->cfg.free(olc); |
| 494 | pool->cache[cidx]->idx[pool->cache[cidx]->len] = idx; |
| 495 | pool->cache[cidx]->len++; |
| 496 | } |
| 497 | |
| 498 | static void |
| 499 | mlx5_ipool_free_cache(struct mlx5_indexed_pool *pool, uint32_t idx) |
no test coverage detected