199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2019 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include <string.h> 6*09e4eceaSJie Zhou #include <sys/queue.h> 799a2dd95SBruce Richardson 899a2dd95SBruce Richardson #include <rte_string_fns.h> 999a2dd95SBruce Richardson #include <rte_atomic.h> 1099a2dd95SBruce Richardson #include <rte_eal.h> 1199a2dd95SBruce Richardson #include <rte_eal_memconfig.h> 1299a2dd95SBruce Richardson #include <rte_errno.h> 1399a2dd95SBruce Richardson #include <rte_malloc.h> 1499a2dd95SBruce Richardson #include <rte_memzone.h> 1599a2dd95SBruce Richardson #include <rte_rwlock.h> 1699a2dd95SBruce Richardson #include <rte_tailq.h> 1799a2dd95SBruce Richardson 1899a2dd95SBruce Richardson #include "rte_stack.h" 1999a2dd95SBruce Richardson #include "stack_pvt.h" 2099a2dd95SBruce Richardson 2199a2dd95SBruce Richardson TAILQ_HEAD(rte_stack_list, rte_tailq_entry); 2299a2dd95SBruce Richardson 2399a2dd95SBruce Richardson static struct rte_tailq_elem rte_stack_tailq = { 2499a2dd95SBruce Richardson .name = RTE_TAILQ_STACK_NAME, 2599a2dd95SBruce Richardson }; 2699a2dd95SBruce Richardson EAL_REGISTER_TAILQ(rte_stack_tailq) 2799a2dd95SBruce Richardson 2899a2dd95SBruce Richardson 2999a2dd95SBruce Richardson static void 3099a2dd95SBruce Richardson rte_stack_init(struct rte_stack *s, unsigned int count, uint32_t flags) 3199a2dd95SBruce Richardson { 3299a2dd95SBruce Richardson memset(s, 0, sizeof(*s)); 3399a2dd95SBruce Richardson 3499a2dd95SBruce Richardson if (flags & RTE_STACK_F_LF) 3599a2dd95SBruce Richardson rte_stack_lf_init(s, count); 3699a2dd95SBruce Richardson else 3799a2dd95SBruce Richardson rte_stack_std_init(s); 3899a2dd95SBruce Richardson } 3999a2dd95SBruce Richardson 4099a2dd95SBruce Richardson static ssize_t 4199a2dd95SBruce Richardson rte_stack_get_memsize(unsigned int count, uint32_t flags) 4299a2dd95SBruce Richardson { 4399a2dd95SBruce Richardson if (flags & RTE_STACK_F_LF) 4499a2dd95SBruce Richardson return rte_stack_lf_get_memsize(count); 4599a2dd95SBruce Richardson else 4699a2dd95SBruce Richardson return rte_stack_std_get_memsize(count); 4799a2dd95SBruce Richardson } 4899a2dd95SBruce Richardson 4999a2dd95SBruce Richardson struct rte_stack * 5099a2dd95SBruce Richardson rte_stack_create(const char *name, unsigned int count, int socket_id, 5199a2dd95SBruce Richardson uint32_t flags) 5299a2dd95SBruce Richardson { 5399a2dd95SBruce Richardson char mz_name[RTE_MEMZONE_NAMESIZE]; 5499a2dd95SBruce Richardson struct rte_stack_list *stack_list; 5599a2dd95SBruce Richardson const struct rte_memzone *mz; 5699a2dd95SBruce Richardson struct rte_tailq_entry *te; 5799a2dd95SBruce Richardson struct rte_stack *s; 5899a2dd95SBruce Richardson unsigned int sz; 5999a2dd95SBruce Richardson int ret; 6099a2dd95SBruce Richardson 6199a2dd95SBruce Richardson if (flags & ~(RTE_STACK_F_LF)) { 6299a2dd95SBruce Richardson STACK_LOG_ERR("Unsupported stack flags %#x\n", flags); 6399a2dd95SBruce Richardson return NULL; 6499a2dd95SBruce Richardson } 6599a2dd95SBruce Richardson 6699a2dd95SBruce Richardson #ifdef RTE_ARCH_64 6799a2dd95SBruce Richardson RTE_BUILD_BUG_ON(sizeof(struct rte_stack_lf_head) != 16); 681abb185dSStanislaw Kardach #endif 691abb185dSStanislaw Kardach #if !defined(RTE_STACK_LF_SUPPORTED) 7099a2dd95SBruce Richardson if (flags & RTE_STACK_F_LF) { 7199a2dd95SBruce Richardson STACK_LOG_ERR("Lock-free stack is not supported on your platform\n"); 721abb185dSStanislaw Kardach rte_errno = ENOTSUP; 7399a2dd95SBruce Richardson return NULL; 7499a2dd95SBruce Richardson } 7599a2dd95SBruce Richardson #endif 7699a2dd95SBruce Richardson 7799a2dd95SBruce Richardson sz = rte_stack_get_memsize(count, flags); 7899a2dd95SBruce Richardson 7999a2dd95SBruce Richardson ret = snprintf(mz_name, sizeof(mz_name), "%s%s", 8099a2dd95SBruce Richardson RTE_STACK_MZ_PREFIX, name); 8199a2dd95SBruce Richardson if (ret < 0 || ret >= (int)sizeof(mz_name)) { 8299a2dd95SBruce Richardson rte_errno = ENAMETOOLONG; 8399a2dd95SBruce Richardson return NULL; 8499a2dd95SBruce Richardson } 8599a2dd95SBruce Richardson 8699a2dd95SBruce Richardson te = rte_zmalloc("STACK_TAILQ_ENTRY", sizeof(*te), 0); 8799a2dd95SBruce Richardson if (te == NULL) { 8899a2dd95SBruce Richardson STACK_LOG_ERR("Cannot reserve memory for tailq\n"); 8999a2dd95SBruce Richardson rte_errno = ENOMEM; 9099a2dd95SBruce Richardson return NULL; 9199a2dd95SBruce Richardson } 9299a2dd95SBruce Richardson 9399a2dd95SBruce Richardson rte_mcfg_tailq_write_lock(); 9499a2dd95SBruce Richardson 9599a2dd95SBruce Richardson mz = rte_memzone_reserve_aligned(mz_name, sz, socket_id, 9699a2dd95SBruce Richardson 0, __alignof__(*s)); 9799a2dd95SBruce Richardson if (mz == NULL) { 9899a2dd95SBruce Richardson STACK_LOG_ERR("Cannot reserve stack memzone!\n"); 9999a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 10099a2dd95SBruce Richardson rte_free(te); 10199a2dd95SBruce Richardson return NULL; 10299a2dd95SBruce Richardson } 10399a2dd95SBruce Richardson 10499a2dd95SBruce Richardson s = mz->addr; 10599a2dd95SBruce Richardson 10699a2dd95SBruce Richardson rte_stack_init(s, count, flags); 10799a2dd95SBruce Richardson 10899a2dd95SBruce Richardson /* Store the name for later lookups */ 10999a2dd95SBruce Richardson ret = strlcpy(s->name, name, sizeof(s->name)); 11099a2dd95SBruce Richardson if (ret < 0 || ret >= (int)sizeof(s->name)) { 11199a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 11299a2dd95SBruce Richardson 11399a2dd95SBruce Richardson rte_errno = ENAMETOOLONG; 11499a2dd95SBruce Richardson rte_free(te); 11599a2dd95SBruce Richardson rte_memzone_free(mz); 11699a2dd95SBruce Richardson return NULL; 11799a2dd95SBruce Richardson } 11899a2dd95SBruce Richardson 11999a2dd95SBruce Richardson s->memzone = mz; 12099a2dd95SBruce Richardson s->capacity = count; 12199a2dd95SBruce Richardson s->flags = flags; 12299a2dd95SBruce Richardson 12399a2dd95SBruce Richardson te->data = s; 12499a2dd95SBruce Richardson 12599a2dd95SBruce Richardson stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list); 12699a2dd95SBruce Richardson 12799a2dd95SBruce Richardson TAILQ_INSERT_TAIL(stack_list, te, next); 12899a2dd95SBruce Richardson 12999a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 13099a2dd95SBruce Richardson 13199a2dd95SBruce Richardson return s; 13299a2dd95SBruce Richardson } 13399a2dd95SBruce Richardson 13499a2dd95SBruce Richardson void 13599a2dd95SBruce Richardson rte_stack_free(struct rte_stack *s) 13699a2dd95SBruce Richardson { 13799a2dd95SBruce Richardson struct rte_stack_list *stack_list; 13899a2dd95SBruce Richardson struct rte_tailq_entry *te; 13999a2dd95SBruce Richardson 14099a2dd95SBruce Richardson if (s == NULL) 14199a2dd95SBruce Richardson return; 14299a2dd95SBruce Richardson 14399a2dd95SBruce Richardson stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list); 14499a2dd95SBruce Richardson rte_mcfg_tailq_write_lock(); 14599a2dd95SBruce Richardson 14699a2dd95SBruce Richardson /* find out tailq entry */ 14799a2dd95SBruce Richardson TAILQ_FOREACH(te, stack_list, next) { 14899a2dd95SBruce Richardson if (te->data == s) 14999a2dd95SBruce Richardson break; 15099a2dd95SBruce Richardson } 15199a2dd95SBruce Richardson 15299a2dd95SBruce Richardson if (te == NULL) { 15399a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 15499a2dd95SBruce Richardson return; 15599a2dd95SBruce Richardson } 15699a2dd95SBruce Richardson 15799a2dd95SBruce Richardson TAILQ_REMOVE(stack_list, te, next); 15899a2dd95SBruce Richardson 15999a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 16099a2dd95SBruce Richardson 16199a2dd95SBruce Richardson rte_free(te); 16299a2dd95SBruce Richardson 16399a2dd95SBruce Richardson rte_memzone_free(s->memzone); 16499a2dd95SBruce Richardson } 16599a2dd95SBruce Richardson 16699a2dd95SBruce Richardson struct rte_stack * 16799a2dd95SBruce Richardson rte_stack_lookup(const char *name) 16899a2dd95SBruce Richardson { 16999a2dd95SBruce Richardson struct rte_stack_list *stack_list; 17099a2dd95SBruce Richardson struct rte_tailq_entry *te; 17199a2dd95SBruce Richardson struct rte_stack *r = NULL; 17299a2dd95SBruce Richardson 17399a2dd95SBruce Richardson if (name == NULL) { 17499a2dd95SBruce Richardson rte_errno = EINVAL; 17599a2dd95SBruce Richardson return NULL; 17699a2dd95SBruce Richardson } 17799a2dd95SBruce Richardson 17899a2dd95SBruce Richardson stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list); 17999a2dd95SBruce Richardson 18099a2dd95SBruce Richardson rte_mcfg_tailq_read_lock(); 18199a2dd95SBruce Richardson 18299a2dd95SBruce Richardson TAILQ_FOREACH(te, stack_list, next) { 18399a2dd95SBruce Richardson r = (struct rte_stack *) te->data; 18499a2dd95SBruce Richardson if (strncmp(name, r->name, RTE_STACK_NAMESIZE) == 0) 18599a2dd95SBruce Richardson break; 18699a2dd95SBruce Richardson } 18799a2dd95SBruce Richardson 18899a2dd95SBruce Richardson rte_mcfg_tailq_read_unlock(); 18999a2dd95SBruce Richardson 19099a2dd95SBruce Richardson if (te == NULL) { 19199a2dd95SBruce Richardson rte_errno = ENOENT; 19299a2dd95SBruce Richardson return NULL; 19399a2dd95SBruce Richardson } 19499a2dd95SBruce Richardson 19599a2dd95SBruce Richardson return r; 19699a2dd95SBruce Richardson } 19799a2dd95SBruce Richardson 198eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(stack_logtype, NOTICE); 199