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