1*99a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2*99a2dd95SBruce Richardson * Copyright(c) 2019 Intel Corporation 3*99a2dd95SBruce Richardson */ 4*99a2dd95SBruce Richardson 5*99a2dd95SBruce Richardson #include <string.h> 6*99a2dd95SBruce Richardson 7*99a2dd95SBruce Richardson #include <rte_string_fns.h> 8*99a2dd95SBruce Richardson #include <rte_atomic.h> 9*99a2dd95SBruce Richardson #include <rte_eal.h> 10*99a2dd95SBruce Richardson #include <rte_eal_memconfig.h> 11*99a2dd95SBruce Richardson #include <rte_errno.h> 12*99a2dd95SBruce Richardson #include <rte_malloc.h> 13*99a2dd95SBruce Richardson #include <rte_memzone.h> 14*99a2dd95SBruce Richardson #include <rte_rwlock.h> 15*99a2dd95SBruce Richardson #include <rte_tailq.h> 16*99a2dd95SBruce Richardson 17*99a2dd95SBruce Richardson #include "rte_stack.h" 18*99a2dd95SBruce Richardson #include "stack_pvt.h" 19*99a2dd95SBruce Richardson 20*99a2dd95SBruce Richardson TAILQ_HEAD(rte_stack_list, rte_tailq_entry); 21*99a2dd95SBruce Richardson 22*99a2dd95SBruce Richardson static struct rte_tailq_elem rte_stack_tailq = { 23*99a2dd95SBruce Richardson .name = RTE_TAILQ_STACK_NAME, 24*99a2dd95SBruce Richardson }; 25*99a2dd95SBruce Richardson EAL_REGISTER_TAILQ(rte_stack_tailq) 26*99a2dd95SBruce Richardson 27*99a2dd95SBruce Richardson 28*99a2dd95SBruce Richardson static void 29*99a2dd95SBruce Richardson rte_stack_init(struct rte_stack *s, unsigned int count, uint32_t flags) 30*99a2dd95SBruce Richardson { 31*99a2dd95SBruce Richardson memset(s, 0, sizeof(*s)); 32*99a2dd95SBruce Richardson 33*99a2dd95SBruce Richardson if (flags & RTE_STACK_F_LF) 34*99a2dd95SBruce Richardson rte_stack_lf_init(s, count); 35*99a2dd95SBruce Richardson else 36*99a2dd95SBruce Richardson rte_stack_std_init(s); 37*99a2dd95SBruce Richardson } 38*99a2dd95SBruce Richardson 39*99a2dd95SBruce Richardson static ssize_t 40*99a2dd95SBruce Richardson rte_stack_get_memsize(unsigned int count, uint32_t flags) 41*99a2dd95SBruce Richardson { 42*99a2dd95SBruce Richardson if (flags & RTE_STACK_F_LF) 43*99a2dd95SBruce Richardson return rte_stack_lf_get_memsize(count); 44*99a2dd95SBruce Richardson else 45*99a2dd95SBruce Richardson return rte_stack_std_get_memsize(count); 46*99a2dd95SBruce Richardson } 47*99a2dd95SBruce Richardson 48*99a2dd95SBruce Richardson struct rte_stack * 49*99a2dd95SBruce Richardson rte_stack_create(const char *name, unsigned int count, int socket_id, 50*99a2dd95SBruce Richardson uint32_t flags) 51*99a2dd95SBruce Richardson { 52*99a2dd95SBruce Richardson char mz_name[RTE_MEMZONE_NAMESIZE]; 53*99a2dd95SBruce Richardson struct rte_stack_list *stack_list; 54*99a2dd95SBruce Richardson const struct rte_memzone *mz; 55*99a2dd95SBruce Richardson struct rte_tailq_entry *te; 56*99a2dd95SBruce Richardson struct rte_stack *s; 57*99a2dd95SBruce Richardson unsigned int sz; 58*99a2dd95SBruce Richardson int ret; 59*99a2dd95SBruce Richardson 60*99a2dd95SBruce Richardson if (flags & ~(RTE_STACK_F_LF)) { 61*99a2dd95SBruce Richardson STACK_LOG_ERR("Unsupported stack flags %#x\n", flags); 62*99a2dd95SBruce Richardson return NULL; 63*99a2dd95SBruce Richardson } 64*99a2dd95SBruce Richardson 65*99a2dd95SBruce Richardson #ifdef RTE_ARCH_64 66*99a2dd95SBruce Richardson RTE_BUILD_BUG_ON(sizeof(struct rte_stack_lf_head) != 16); 67*99a2dd95SBruce Richardson #else 68*99a2dd95SBruce Richardson if (flags & RTE_STACK_F_LF) { 69*99a2dd95SBruce Richardson STACK_LOG_ERR("Lock-free stack is not supported on your platform\n"); 70*99a2dd95SBruce Richardson return NULL; 71*99a2dd95SBruce Richardson } 72*99a2dd95SBruce Richardson #endif 73*99a2dd95SBruce Richardson 74*99a2dd95SBruce Richardson sz = rte_stack_get_memsize(count, flags); 75*99a2dd95SBruce Richardson 76*99a2dd95SBruce Richardson ret = snprintf(mz_name, sizeof(mz_name), "%s%s", 77*99a2dd95SBruce Richardson RTE_STACK_MZ_PREFIX, name); 78*99a2dd95SBruce Richardson if (ret < 0 || ret >= (int)sizeof(mz_name)) { 79*99a2dd95SBruce Richardson rte_errno = ENAMETOOLONG; 80*99a2dd95SBruce Richardson return NULL; 81*99a2dd95SBruce Richardson } 82*99a2dd95SBruce Richardson 83*99a2dd95SBruce Richardson te = rte_zmalloc("STACK_TAILQ_ENTRY", sizeof(*te), 0); 84*99a2dd95SBruce Richardson if (te == NULL) { 85*99a2dd95SBruce Richardson STACK_LOG_ERR("Cannot reserve memory for tailq\n"); 86*99a2dd95SBruce Richardson rte_errno = ENOMEM; 87*99a2dd95SBruce Richardson return NULL; 88*99a2dd95SBruce Richardson } 89*99a2dd95SBruce Richardson 90*99a2dd95SBruce Richardson rte_mcfg_tailq_write_lock(); 91*99a2dd95SBruce Richardson 92*99a2dd95SBruce Richardson mz = rte_memzone_reserve_aligned(mz_name, sz, socket_id, 93*99a2dd95SBruce Richardson 0, __alignof__(*s)); 94*99a2dd95SBruce Richardson if (mz == NULL) { 95*99a2dd95SBruce Richardson STACK_LOG_ERR("Cannot reserve stack memzone!\n"); 96*99a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 97*99a2dd95SBruce Richardson rte_free(te); 98*99a2dd95SBruce Richardson return NULL; 99*99a2dd95SBruce Richardson } 100*99a2dd95SBruce Richardson 101*99a2dd95SBruce Richardson s = mz->addr; 102*99a2dd95SBruce Richardson 103*99a2dd95SBruce Richardson rte_stack_init(s, count, flags); 104*99a2dd95SBruce Richardson 105*99a2dd95SBruce Richardson /* Store the name for later lookups */ 106*99a2dd95SBruce Richardson ret = strlcpy(s->name, name, sizeof(s->name)); 107*99a2dd95SBruce Richardson if (ret < 0 || ret >= (int)sizeof(s->name)) { 108*99a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 109*99a2dd95SBruce Richardson 110*99a2dd95SBruce Richardson rte_errno = ENAMETOOLONG; 111*99a2dd95SBruce Richardson rte_free(te); 112*99a2dd95SBruce Richardson rte_memzone_free(mz); 113*99a2dd95SBruce Richardson return NULL; 114*99a2dd95SBruce Richardson } 115*99a2dd95SBruce Richardson 116*99a2dd95SBruce Richardson s->memzone = mz; 117*99a2dd95SBruce Richardson s->capacity = count; 118*99a2dd95SBruce Richardson s->flags = flags; 119*99a2dd95SBruce Richardson 120*99a2dd95SBruce Richardson te->data = s; 121*99a2dd95SBruce Richardson 122*99a2dd95SBruce Richardson stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list); 123*99a2dd95SBruce Richardson 124*99a2dd95SBruce Richardson TAILQ_INSERT_TAIL(stack_list, te, next); 125*99a2dd95SBruce Richardson 126*99a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 127*99a2dd95SBruce Richardson 128*99a2dd95SBruce Richardson return s; 129*99a2dd95SBruce Richardson } 130*99a2dd95SBruce Richardson 131*99a2dd95SBruce Richardson void 132*99a2dd95SBruce Richardson rte_stack_free(struct rte_stack *s) 133*99a2dd95SBruce Richardson { 134*99a2dd95SBruce Richardson struct rte_stack_list *stack_list; 135*99a2dd95SBruce Richardson struct rte_tailq_entry *te; 136*99a2dd95SBruce Richardson 137*99a2dd95SBruce Richardson if (s == NULL) 138*99a2dd95SBruce Richardson return; 139*99a2dd95SBruce Richardson 140*99a2dd95SBruce Richardson stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list); 141*99a2dd95SBruce Richardson rte_mcfg_tailq_write_lock(); 142*99a2dd95SBruce Richardson 143*99a2dd95SBruce Richardson /* find out tailq entry */ 144*99a2dd95SBruce Richardson TAILQ_FOREACH(te, stack_list, next) { 145*99a2dd95SBruce Richardson if (te->data == s) 146*99a2dd95SBruce Richardson break; 147*99a2dd95SBruce Richardson } 148*99a2dd95SBruce Richardson 149*99a2dd95SBruce Richardson if (te == NULL) { 150*99a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 151*99a2dd95SBruce Richardson return; 152*99a2dd95SBruce Richardson } 153*99a2dd95SBruce Richardson 154*99a2dd95SBruce Richardson TAILQ_REMOVE(stack_list, te, next); 155*99a2dd95SBruce Richardson 156*99a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 157*99a2dd95SBruce Richardson 158*99a2dd95SBruce Richardson rte_free(te); 159*99a2dd95SBruce Richardson 160*99a2dd95SBruce Richardson rte_memzone_free(s->memzone); 161*99a2dd95SBruce Richardson } 162*99a2dd95SBruce Richardson 163*99a2dd95SBruce Richardson struct rte_stack * 164*99a2dd95SBruce Richardson rte_stack_lookup(const char *name) 165*99a2dd95SBruce Richardson { 166*99a2dd95SBruce Richardson struct rte_stack_list *stack_list; 167*99a2dd95SBruce Richardson struct rte_tailq_entry *te; 168*99a2dd95SBruce Richardson struct rte_stack *r = NULL; 169*99a2dd95SBruce Richardson 170*99a2dd95SBruce Richardson if (name == NULL) { 171*99a2dd95SBruce Richardson rte_errno = EINVAL; 172*99a2dd95SBruce Richardson return NULL; 173*99a2dd95SBruce Richardson } 174*99a2dd95SBruce Richardson 175*99a2dd95SBruce Richardson stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list); 176*99a2dd95SBruce Richardson 177*99a2dd95SBruce Richardson rte_mcfg_tailq_read_lock(); 178*99a2dd95SBruce Richardson 179*99a2dd95SBruce Richardson TAILQ_FOREACH(te, stack_list, next) { 180*99a2dd95SBruce Richardson r = (struct rte_stack *) te->data; 181*99a2dd95SBruce Richardson if (strncmp(name, r->name, RTE_STACK_NAMESIZE) == 0) 182*99a2dd95SBruce Richardson break; 183*99a2dd95SBruce Richardson } 184*99a2dd95SBruce Richardson 185*99a2dd95SBruce Richardson rte_mcfg_tailq_read_unlock(); 186*99a2dd95SBruce Richardson 187*99a2dd95SBruce Richardson if (te == NULL) { 188*99a2dd95SBruce Richardson rte_errno = ENOENT; 189*99a2dd95SBruce Richardson return NULL; 190*99a2dd95SBruce Richardson } 191*99a2dd95SBruce Richardson 192*99a2dd95SBruce Richardson return r; 193*99a2dd95SBruce Richardson } 194*99a2dd95SBruce Richardson 195*99a2dd95SBruce Richardson RTE_LOG_REGISTER(stack_logtype, lib.stack, NOTICE); 196