14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang * Copyright(c) 2019 Intel Corporation
34418919fSjohnjiang */
44418919fSjohnjiang
54418919fSjohnjiang #include <string.h>
64418919fSjohnjiang
74418919fSjohnjiang #include <rte_string_fns.h>
84418919fSjohnjiang #include <rte_atomic.h>
94418919fSjohnjiang #include <rte_eal.h>
104418919fSjohnjiang #include <rte_eal_memconfig.h>
114418919fSjohnjiang #include <rte_errno.h>
124418919fSjohnjiang #include <rte_malloc.h>
134418919fSjohnjiang #include <rte_memzone.h>
144418919fSjohnjiang #include <rte_rwlock.h>
154418919fSjohnjiang #include <rte_tailq.h>
164418919fSjohnjiang
174418919fSjohnjiang #include "rte_stack.h"
184418919fSjohnjiang #include "stack_pvt.h"
194418919fSjohnjiang
204418919fSjohnjiang TAILQ_HEAD(rte_stack_list, rte_tailq_entry);
214418919fSjohnjiang
224418919fSjohnjiang static struct rte_tailq_elem rte_stack_tailq = {
234418919fSjohnjiang .name = RTE_TAILQ_STACK_NAME,
244418919fSjohnjiang };
EAL_REGISTER_TAILQ(rte_stack_tailq)254418919fSjohnjiang EAL_REGISTER_TAILQ(rte_stack_tailq)
264418919fSjohnjiang
274418919fSjohnjiang
284418919fSjohnjiang static void
294418919fSjohnjiang rte_stack_init(struct rte_stack *s, unsigned int count, uint32_t flags)
304418919fSjohnjiang {
314418919fSjohnjiang memset(s, 0, sizeof(*s));
324418919fSjohnjiang
334418919fSjohnjiang if (flags & RTE_STACK_F_LF)
344418919fSjohnjiang rte_stack_lf_init(s, count);
354418919fSjohnjiang else
364418919fSjohnjiang rte_stack_std_init(s);
374418919fSjohnjiang }
384418919fSjohnjiang
394418919fSjohnjiang static ssize_t
rte_stack_get_memsize(unsigned int count,uint32_t flags)404418919fSjohnjiang rte_stack_get_memsize(unsigned int count, uint32_t flags)
414418919fSjohnjiang {
424418919fSjohnjiang if (flags & RTE_STACK_F_LF)
434418919fSjohnjiang return rte_stack_lf_get_memsize(count);
444418919fSjohnjiang else
454418919fSjohnjiang return rte_stack_std_get_memsize(count);
464418919fSjohnjiang }
474418919fSjohnjiang
484418919fSjohnjiang struct rte_stack *
rte_stack_create(const char * name,unsigned int count,int socket_id,uint32_t flags)494418919fSjohnjiang rte_stack_create(const char *name, unsigned int count, int socket_id,
504418919fSjohnjiang uint32_t flags)
514418919fSjohnjiang {
524418919fSjohnjiang char mz_name[RTE_MEMZONE_NAMESIZE];
534418919fSjohnjiang struct rte_stack_list *stack_list;
544418919fSjohnjiang const struct rte_memzone *mz;
554418919fSjohnjiang struct rte_tailq_entry *te;
564418919fSjohnjiang struct rte_stack *s;
574418919fSjohnjiang unsigned int sz;
584418919fSjohnjiang int ret;
594418919fSjohnjiang
60*2d9fd380Sjfb8856606 if (flags & ~(RTE_STACK_F_LF)) {
61*2d9fd380Sjfb8856606 STACK_LOG_ERR("Unsupported stack flags %#x\n", flags);
62*2d9fd380Sjfb8856606 return NULL;
63*2d9fd380Sjfb8856606 }
64*2d9fd380Sjfb8856606
654418919fSjohnjiang #ifdef RTE_ARCH_64
664418919fSjohnjiang RTE_BUILD_BUG_ON(sizeof(struct rte_stack_lf_head) != 16);
674418919fSjohnjiang #else
684418919fSjohnjiang if (flags & RTE_STACK_F_LF) {
694418919fSjohnjiang STACK_LOG_ERR("Lock-free stack is not supported on your platform\n");
704418919fSjohnjiang return NULL;
714418919fSjohnjiang }
724418919fSjohnjiang #endif
734418919fSjohnjiang
744418919fSjohnjiang sz = rte_stack_get_memsize(count, flags);
754418919fSjohnjiang
764418919fSjohnjiang ret = snprintf(mz_name, sizeof(mz_name), "%s%s",
774418919fSjohnjiang RTE_STACK_MZ_PREFIX, name);
784418919fSjohnjiang if (ret < 0 || ret >= (int)sizeof(mz_name)) {
794418919fSjohnjiang rte_errno = ENAMETOOLONG;
804418919fSjohnjiang return NULL;
814418919fSjohnjiang }
824418919fSjohnjiang
834418919fSjohnjiang te = rte_zmalloc("STACK_TAILQ_ENTRY", sizeof(*te), 0);
844418919fSjohnjiang if (te == NULL) {
854418919fSjohnjiang STACK_LOG_ERR("Cannot reserve memory for tailq\n");
864418919fSjohnjiang rte_errno = ENOMEM;
874418919fSjohnjiang return NULL;
884418919fSjohnjiang }
894418919fSjohnjiang
904418919fSjohnjiang rte_mcfg_tailq_write_lock();
914418919fSjohnjiang
924418919fSjohnjiang mz = rte_memzone_reserve_aligned(mz_name, sz, socket_id,
934418919fSjohnjiang 0, __alignof__(*s));
944418919fSjohnjiang if (mz == NULL) {
954418919fSjohnjiang STACK_LOG_ERR("Cannot reserve stack memzone!\n");
964418919fSjohnjiang rte_mcfg_tailq_write_unlock();
974418919fSjohnjiang rte_free(te);
984418919fSjohnjiang return NULL;
994418919fSjohnjiang }
1004418919fSjohnjiang
1014418919fSjohnjiang s = mz->addr;
1024418919fSjohnjiang
1034418919fSjohnjiang rte_stack_init(s, count, flags);
1044418919fSjohnjiang
1054418919fSjohnjiang /* Store the name for later lookups */
1064418919fSjohnjiang ret = strlcpy(s->name, name, sizeof(s->name));
1074418919fSjohnjiang if (ret < 0 || ret >= (int)sizeof(s->name)) {
1084418919fSjohnjiang rte_mcfg_tailq_write_unlock();
1094418919fSjohnjiang
1104418919fSjohnjiang rte_errno = ENAMETOOLONG;
1114418919fSjohnjiang rte_free(te);
1124418919fSjohnjiang rte_memzone_free(mz);
1134418919fSjohnjiang return NULL;
1144418919fSjohnjiang }
1154418919fSjohnjiang
1164418919fSjohnjiang s->memzone = mz;
1174418919fSjohnjiang s->capacity = count;
1184418919fSjohnjiang s->flags = flags;
1194418919fSjohnjiang
1204418919fSjohnjiang te->data = s;
1214418919fSjohnjiang
1224418919fSjohnjiang stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
1234418919fSjohnjiang
1244418919fSjohnjiang TAILQ_INSERT_TAIL(stack_list, te, next);
1254418919fSjohnjiang
1264418919fSjohnjiang rte_mcfg_tailq_write_unlock();
1274418919fSjohnjiang
1284418919fSjohnjiang return s;
1294418919fSjohnjiang }
1304418919fSjohnjiang
1314418919fSjohnjiang void
rte_stack_free(struct rte_stack * s)1324418919fSjohnjiang rte_stack_free(struct rte_stack *s)
1334418919fSjohnjiang {
1344418919fSjohnjiang struct rte_stack_list *stack_list;
1354418919fSjohnjiang struct rte_tailq_entry *te;
1364418919fSjohnjiang
1374418919fSjohnjiang if (s == NULL)
1384418919fSjohnjiang return;
1394418919fSjohnjiang
1404418919fSjohnjiang stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
1414418919fSjohnjiang rte_mcfg_tailq_write_lock();
1424418919fSjohnjiang
1434418919fSjohnjiang /* find out tailq entry */
1444418919fSjohnjiang TAILQ_FOREACH(te, stack_list, next) {
1454418919fSjohnjiang if (te->data == s)
1464418919fSjohnjiang break;
1474418919fSjohnjiang }
1484418919fSjohnjiang
1494418919fSjohnjiang if (te == NULL) {
1504418919fSjohnjiang rte_mcfg_tailq_write_unlock();
1514418919fSjohnjiang return;
1524418919fSjohnjiang }
1534418919fSjohnjiang
1544418919fSjohnjiang TAILQ_REMOVE(stack_list, te, next);
1554418919fSjohnjiang
1564418919fSjohnjiang rte_mcfg_tailq_write_unlock();
1574418919fSjohnjiang
1584418919fSjohnjiang rte_free(te);
1594418919fSjohnjiang
1604418919fSjohnjiang rte_memzone_free(s->memzone);
1614418919fSjohnjiang }
1624418919fSjohnjiang
1634418919fSjohnjiang struct rte_stack *
rte_stack_lookup(const char * name)1644418919fSjohnjiang rte_stack_lookup(const char *name)
1654418919fSjohnjiang {
1664418919fSjohnjiang struct rte_stack_list *stack_list;
1674418919fSjohnjiang struct rte_tailq_entry *te;
1684418919fSjohnjiang struct rte_stack *r = NULL;
1694418919fSjohnjiang
1704418919fSjohnjiang if (name == NULL) {
1714418919fSjohnjiang rte_errno = EINVAL;
1724418919fSjohnjiang return NULL;
1734418919fSjohnjiang }
1744418919fSjohnjiang
1754418919fSjohnjiang stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
1764418919fSjohnjiang
1774418919fSjohnjiang rte_mcfg_tailq_read_lock();
1784418919fSjohnjiang
1794418919fSjohnjiang TAILQ_FOREACH(te, stack_list, next) {
1804418919fSjohnjiang r = (struct rte_stack *) te->data;
1814418919fSjohnjiang if (strncmp(name, r->name, RTE_STACK_NAMESIZE) == 0)
1824418919fSjohnjiang break;
1834418919fSjohnjiang }
1844418919fSjohnjiang
1854418919fSjohnjiang rte_mcfg_tailq_read_unlock();
1864418919fSjohnjiang
1874418919fSjohnjiang if (te == NULL) {
1884418919fSjohnjiang rte_errno = ENOENT;
1894418919fSjohnjiang return NULL;
1904418919fSjohnjiang }
1914418919fSjohnjiang
1924418919fSjohnjiang return r;
1934418919fSjohnjiang }
1944418919fSjohnjiang
195*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(stack_logtype, lib.stack, NOTICE);
196