1*b5458e2cSKonstantin Ananyev /* SPDX-License-Identifier: BSD-3-Clause 2*b5458e2cSKonstantin Ananyev * Copyright(c) 2024 Huawei Technologies Co., Ltd 3*b5458e2cSKonstantin Ananyev */ 4*b5458e2cSKonstantin Ananyev 5*b5458e2cSKonstantin Ananyev #include <inttypes.h> 6*b5458e2cSKonstantin Ananyev 7*b5458e2cSKonstantin Ananyev #include <rte_string_fns.h> 8*b5458e2cSKonstantin Ananyev 9*b5458e2cSKonstantin Ananyev #include "soring.h" 10*b5458e2cSKonstantin Ananyev 11*b5458e2cSKonstantin Ananyev RTE_LOG_REGISTER_DEFAULT(soring_logtype, INFO); 12*b5458e2cSKonstantin Ananyev 13*b5458e2cSKonstantin Ananyev static uint32_t 14*b5458e2cSKonstantin Ananyev soring_calc_elem_num(uint32_t count) 15*b5458e2cSKonstantin Ananyev { 16*b5458e2cSKonstantin Ananyev return rte_align32pow2(count + 1); 17*b5458e2cSKonstantin Ananyev } 18*b5458e2cSKonstantin Ananyev 19*b5458e2cSKonstantin Ananyev static int 20*b5458e2cSKonstantin Ananyev soring_check_param(uint32_t esize, uint32_t msize, uint32_t count, 21*b5458e2cSKonstantin Ananyev uint32_t stages) 22*b5458e2cSKonstantin Ananyev { 23*b5458e2cSKonstantin Ananyev if (stages == 0) { 24*b5458e2cSKonstantin Ananyev SORING_LOG(ERR, "invalid number of stages: %u", stages); 25*b5458e2cSKonstantin Ananyev return -EINVAL; 26*b5458e2cSKonstantin Ananyev } 27*b5458e2cSKonstantin Ananyev 28*b5458e2cSKonstantin Ananyev /* Check if element size is a multiple of 4B */ 29*b5458e2cSKonstantin Ananyev if (esize == 0 || esize % 4 != 0) { 30*b5458e2cSKonstantin Ananyev SORING_LOG(ERR, "invalid element size: %u", esize); 31*b5458e2cSKonstantin Ananyev return -EINVAL; 32*b5458e2cSKonstantin Ananyev } 33*b5458e2cSKonstantin Ananyev 34*b5458e2cSKonstantin Ananyev /* Check if size of metadata is a multiple of 4B */ 35*b5458e2cSKonstantin Ananyev if (msize % 4 != 0) { 36*b5458e2cSKonstantin Ananyev SORING_LOG(ERR, "invalid metadata size: %u", msize); 37*b5458e2cSKonstantin Ananyev return -EINVAL; 38*b5458e2cSKonstantin Ananyev } 39*b5458e2cSKonstantin Ananyev 40*b5458e2cSKonstantin Ananyev /* count must be a power of 2 */ 41*b5458e2cSKonstantin Ananyev if (rte_is_power_of_2(count) == 0 || 42*b5458e2cSKonstantin Ananyev (count > RTE_SORING_ELEM_MAX + 1)) { 43*b5458e2cSKonstantin Ananyev SORING_LOG(ERR, "invalid number of elements: %u", count); 44*b5458e2cSKonstantin Ananyev return -EINVAL; 45*b5458e2cSKonstantin Ananyev } 46*b5458e2cSKonstantin Ananyev 47*b5458e2cSKonstantin Ananyev return 0; 48*b5458e2cSKonstantin Ananyev } 49*b5458e2cSKonstantin Ananyev 50*b5458e2cSKonstantin Ananyev /* 51*b5458e2cSKonstantin Ananyev * Calculate size offsets for SORING internal data layout. 52*b5458e2cSKonstantin Ananyev */ 53*b5458e2cSKonstantin Ananyev static size_t 54*b5458e2cSKonstantin Ananyev soring_get_szofs(uint32_t esize, uint32_t msize, uint32_t count, 55*b5458e2cSKonstantin Ananyev uint32_t stages, size_t *elst_ofs, size_t *state_ofs, 56*b5458e2cSKonstantin Ananyev size_t *stage_ofs) 57*b5458e2cSKonstantin Ananyev { 58*b5458e2cSKonstantin Ananyev size_t sz; 59*b5458e2cSKonstantin Ananyev const struct rte_soring * const r = NULL; 60*b5458e2cSKonstantin Ananyev 61*b5458e2cSKonstantin Ananyev sz = sizeof(r[0]) + (size_t)count * esize; 62*b5458e2cSKonstantin Ananyev sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE); 63*b5458e2cSKonstantin Ananyev 64*b5458e2cSKonstantin Ananyev if (elst_ofs != NULL) 65*b5458e2cSKonstantin Ananyev *elst_ofs = sz; 66*b5458e2cSKonstantin Ananyev 67*b5458e2cSKonstantin Ananyev sz = sz + (size_t)count * msize; 68*b5458e2cSKonstantin Ananyev sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE); 69*b5458e2cSKonstantin Ananyev 70*b5458e2cSKonstantin Ananyev if (state_ofs != NULL) 71*b5458e2cSKonstantin Ananyev *state_ofs = sz; 72*b5458e2cSKonstantin Ananyev 73*b5458e2cSKonstantin Ananyev sz += sizeof(r->state[0]) * count; 74*b5458e2cSKonstantin Ananyev sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE); 75*b5458e2cSKonstantin Ananyev 76*b5458e2cSKonstantin Ananyev if (stage_ofs != NULL) 77*b5458e2cSKonstantin Ananyev *stage_ofs = sz; 78*b5458e2cSKonstantin Ananyev 79*b5458e2cSKonstantin Ananyev sz += sizeof(r->stage[0]) * stages; 80*b5458e2cSKonstantin Ananyev sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE); 81*b5458e2cSKonstantin Ananyev 82*b5458e2cSKonstantin Ananyev return sz; 83*b5458e2cSKonstantin Ananyev } 84*b5458e2cSKonstantin Ananyev 85*b5458e2cSKonstantin Ananyev static void 86*b5458e2cSKonstantin Ananyev soring_dump_stage_headtail(FILE *f, const char *prefix, 87*b5458e2cSKonstantin Ananyev struct soring_stage *st) 88*b5458e2cSKonstantin Ananyev { 89*b5458e2cSKonstantin Ananyev fprintf(f, "%stail.pos=%"PRIu32"\n", prefix, st->sht.tail.pos); 90*b5458e2cSKonstantin Ananyev fprintf(f, "%stail.sync=%"PRIu32"\n", prefix, st->sht.tail.sync); 91*b5458e2cSKonstantin Ananyev fprintf(f, "%shead=%"PRIu32"\n", prefix, st->sht.head); 92*b5458e2cSKonstantin Ananyev } 93*b5458e2cSKonstantin Ananyev 94*b5458e2cSKonstantin Ananyev void 95*b5458e2cSKonstantin Ananyev rte_soring_dump(FILE *f, const struct rte_soring *r) 96*b5458e2cSKonstantin Ananyev { 97*b5458e2cSKonstantin Ananyev uint32_t i; 98*b5458e2cSKonstantin Ananyev char buf[32]; 99*b5458e2cSKonstantin Ananyev 100*b5458e2cSKonstantin Ananyev if (f == NULL || r == NULL) 101*b5458e2cSKonstantin Ananyev return; 102*b5458e2cSKonstantin Ananyev 103*b5458e2cSKonstantin Ananyev fprintf(f, "soring <%s>@%p\n", r->name, r); 104*b5458e2cSKonstantin Ananyev fprintf(f, " size=%"PRIu32"\n", r->size); 105*b5458e2cSKonstantin Ananyev fprintf(f, " capacity=%"PRIu32"\n", r->capacity); 106*b5458e2cSKonstantin Ananyev fprintf(f, " esize=%"PRIu32"\n", r->esize); 107*b5458e2cSKonstantin Ananyev fprintf(f, " msize=%"PRIu32"\n", r->msize); 108*b5458e2cSKonstantin Ananyev fprintf(f, " used=%u\n", rte_soring_count(r)); 109*b5458e2cSKonstantin Ananyev fprintf(f, " avail=%u\n", rte_soring_free_count(r)); 110*b5458e2cSKonstantin Ananyev 111*b5458e2cSKonstantin Ananyev rte_ring_headtail_dump(f, " cons.", &(r->cons.ht)); 112*b5458e2cSKonstantin Ananyev rte_ring_headtail_dump(f, " prod.", &(r->prod.ht)); 113*b5458e2cSKonstantin Ananyev 114*b5458e2cSKonstantin Ananyev fprintf(f, " nb_stage=%"PRIu32"\n", r->nb_stage); 115*b5458e2cSKonstantin Ananyev for (i = 0; i < r->nb_stage; i++) { 116*b5458e2cSKonstantin Ananyev snprintf(buf, sizeof(buf), " stage[%u].", i); 117*b5458e2cSKonstantin Ananyev soring_dump_stage_headtail(f, buf, r->stage + i); 118*b5458e2cSKonstantin Ananyev } 119*b5458e2cSKonstantin Ananyev } 120*b5458e2cSKonstantin Ananyev 121*b5458e2cSKonstantin Ananyev ssize_t 122*b5458e2cSKonstantin Ananyev rte_soring_get_memsize(const struct rte_soring_param *prm) 123*b5458e2cSKonstantin Ananyev { 124*b5458e2cSKonstantin Ananyev int32_t rc; 125*b5458e2cSKonstantin Ananyev uint32_t count; 126*b5458e2cSKonstantin Ananyev 127*b5458e2cSKonstantin Ananyev count = soring_calc_elem_num(prm->elems); 128*b5458e2cSKonstantin Ananyev rc = soring_check_param(prm->elem_size, prm->meta_size, count, 129*b5458e2cSKonstantin Ananyev prm->stages); 130*b5458e2cSKonstantin Ananyev if (rc != 0) 131*b5458e2cSKonstantin Ananyev return rc; 132*b5458e2cSKonstantin Ananyev 133*b5458e2cSKonstantin Ananyev return soring_get_szofs(prm->elem_size, prm->meta_size, count, 134*b5458e2cSKonstantin Ananyev prm->stages, NULL, NULL, NULL); 135*b5458e2cSKonstantin Ananyev } 136*b5458e2cSKonstantin Ananyev 137*b5458e2cSKonstantin Ananyev /* compilation-time checks */ 138*b5458e2cSKonstantin Ananyev static void 139*b5458e2cSKonstantin Ananyev soring_compilation_checks(void) 140*b5458e2cSKonstantin Ananyev { 141*b5458e2cSKonstantin Ananyev RTE_BUILD_BUG_ON((sizeof(struct rte_soring) & 142*b5458e2cSKonstantin Ananyev RTE_CACHE_LINE_MASK) != 0); 143*b5458e2cSKonstantin Ananyev RTE_BUILD_BUG_ON((offsetof(struct rte_soring, cons) & 144*b5458e2cSKonstantin Ananyev RTE_CACHE_LINE_MASK) != 0); 145*b5458e2cSKonstantin Ananyev RTE_BUILD_BUG_ON((offsetof(struct rte_soring, prod) & 146*b5458e2cSKonstantin Ananyev RTE_CACHE_LINE_MASK) != 0); 147*b5458e2cSKonstantin Ananyev 148*b5458e2cSKonstantin Ananyev RTE_BUILD_BUG_ON(offsetof(struct rte_ring_headtail, tail) != 149*b5458e2cSKonstantin Ananyev offsetof(struct soring_stage_headtail, tail.pos)); 150*b5458e2cSKonstantin Ananyev RTE_BUILD_BUG_ON(offsetof(struct rte_ring_headtail, sync_type) != 151*b5458e2cSKonstantin Ananyev offsetof(struct soring_stage_headtail, unused)); 152*b5458e2cSKonstantin Ananyev } 153*b5458e2cSKonstantin Ananyev 154*b5458e2cSKonstantin Ananyev int 155*b5458e2cSKonstantin Ananyev rte_soring_init(struct rte_soring *r, const struct rte_soring_param *prm) 156*b5458e2cSKonstantin Ananyev { 157*b5458e2cSKonstantin Ananyev int32_t rc; 158*b5458e2cSKonstantin Ananyev uint32_t n; 159*b5458e2cSKonstantin Ananyev size_t meta_ofs, stage_ofs, state_ofs; 160*b5458e2cSKonstantin Ananyev 161*b5458e2cSKonstantin Ananyev soring_compilation_checks(); 162*b5458e2cSKonstantin Ananyev 163*b5458e2cSKonstantin Ananyev if (r == NULL || prm == NULL) 164*b5458e2cSKonstantin Ananyev return -EINVAL; 165*b5458e2cSKonstantin Ananyev 166*b5458e2cSKonstantin Ananyev n = soring_calc_elem_num(prm->elems); 167*b5458e2cSKonstantin Ananyev rc = soring_check_param(prm->elem_size, prm->meta_size, n, prm->stages); 168*b5458e2cSKonstantin Ananyev if (rc != 0) 169*b5458e2cSKonstantin Ananyev return rc; 170*b5458e2cSKonstantin Ananyev 171*b5458e2cSKonstantin Ananyev soring_get_szofs(prm->elem_size, prm->meta_size, n, prm->stages, 172*b5458e2cSKonstantin Ananyev &meta_ofs, &state_ofs, &stage_ofs); 173*b5458e2cSKonstantin Ananyev 174*b5458e2cSKonstantin Ananyev memset(r, 0, sizeof(*r)); 175*b5458e2cSKonstantin Ananyev rc = strlcpy(r->name, prm->name, sizeof(r->name)); 176*b5458e2cSKonstantin Ananyev if (rc < 0 || rc >= (int)sizeof(r->name)) 177*b5458e2cSKonstantin Ananyev return -ENAMETOOLONG; 178*b5458e2cSKonstantin Ananyev 179*b5458e2cSKonstantin Ananyev r->size = n; 180*b5458e2cSKonstantin Ananyev r->mask = r->size - 1; 181*b5458e2cSKonstantin Ananyev r->capacity = prm->elems; 182*b5458e2cSKonstantin Ananyev r->esize = prm->elem_size; 183*b5458e2cSKonstantin Ananyev r->msize = prm->meta_size; 184*b5458e2cSKonstantin Ananyev 185*b5458e2cSKonstantin Ananyev r->prod.ht.sync_type = prm->prod_synt; 186*b5458e2cSKonstantin Ananyev r->cons.ht.sync_type = prm->cons_synt; 187*b5458e2cSKonstantin Ananyev 188*b5458e2cSKonstantin Ananyev r->state = (union soring_state *)((uintptr_t)r + state_ofs); 189*b5458e2cSKonstantin Ananyev memset(r->state, 0, sizeof(r->state[0]) * r->size); 190*b5458e2cSKonstantin Ananyev 191*b5458e2cSKonstantin Ananyev r->stage = (struct soring_stage *)((uintptr_t)r + stage_ofs); 192*b5458e2cSKonstantin Ananyev r->nb_stage = prm->stages; 193*b5458e2cSKonstantin Ananyev memset(r->stage, 0, r->nb_stage * sizeof(r->stage[0])); 194*b5458e2cSKonstantin Ananyev 195*b5458e2cSKonstantin Ananyev if (r->msize != 0) 196*b5458e2cSKonstantin Ananyev r->meta = (void *)((uintptr_t)r + meta_ofs); 197*b5458e2cSKonstantin Ananyev 198*b5458e2cSKonstantin Ananyev return 0; 199*b5458e2cSKonstantin Ananyev } 200