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