1703faabfSKonstantin Ananyev/*
2703faabfSKonstantin Ananyev * Copyright (c) 2019  Intel Corporation.
3703faabfSKonstantin Ananyev * Licensed under the Apache License, Version 2.0 (the "License");
4703faabfSKonstantin Ananyev * you may not use this file except in compliance with the License.
5703faabfSKonstantin Ananyev * You may obtain a copy of the License at:
6703faabfSKonstantin Ananyev *
7703faabfSKonstantin Ananyev *     http://www.apache.org/licenses/LICENSE-2.0
8703faabfSKonstantin Ananyev *
9703faabfSKonstantin Ananyev * Unless required by applicable law or agreed to in writing, software
10703faabfSKonstantin Ananyev * distributed under the License is distributed on an "AS IS" BASIS,
11703faabfSKonstantin Ananyev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12703faabfSKonstantin Ananyev * See the License for the specific language governing permissions and
13703faabfSKonstantin Ananyev * limitations under the License.
14703faabfSKonstantin Ananyev */
15703faabfSKonstantin Ananyev
16703faabfSKonstantin Ananyev#ifndef	_MEMTANK_H_
17703faabfSKonstantin Ananyev#define	_MEMTANK_H_
18703faabfSKonstantin Ananyev
19703faabfSKonstantin Ananyev#include <tle_memtank.h>
20703faabfSKonstantin Ananyev#include <stdalign.h>
21703faabfSKonstantin Ananyev
22703faabfSKonstantin Ananyevstruct memobj {
23703faabfSKonstantin Ananyev	uint64_t red_zone1;
24703faabfSKonstantin Ananyev	struct memchunk *chunk; /* ptr to the chunk it belongs to */
25703faabfSKonstantin Ananyev	struct {
26703faabfSKonstantin Ananyev		uint32_t nb_alloc;
27703faabfSKonstantin Ananyev		uint32_t nb_free;
28703faabfSKonstantin Ananyev	} dbg;
29703faabfSKonstantin Ananyev	uint64_t red_zone2;
30703faabfSKonstantin Ananyev};
31703faabfSKonstantin Ananyev
32703faabfSKonstantin Ananyev#define RED_ZONE_V1	UINT64_C(0xBADECAFEBADECAFE)
33703faabfSKonstantin Ananyev#define RED_ZONE_V2	UINT64_C(0xDEADBEEFDEADBEEF)
34703faabfSKonstantin Ananyev
35703faabfSKonstantin Ananyevstruct memchunk {
36703faabfSKonstantin Ananyev	TAILQ_ENTRY(memchunk) link;  /* link to the next chunk in the tank */
37703faabfSKonstantin Ananyev	void *raw;		     /* un-aligned ptr returned by alloc() */
38703faabfSKonstantin Ananyev	uint32_t nb_total;           /* total number of objects in the chunk */
39703faabfSKonstantin Ananyev	uint32_t nb_free;            /*  number of free object in the chunk */
40703faabfSKonstantin Ananyev	void *free[];                /* array of free objects */
41703faabfSKonstantin Ananyev} __rte_cache_aligned;
42703faabfSKonstantin Ananyev
43703faabfSKonstantin Ananyev
44703faabfSKonstantin AnanyevTAILQ_HEAD(mchunk_head, memchunk);
45703faabfSKonstantin Ananyev
46703faabfSKonstantin Ananyevstruct mchunk_list {
47703faabfSKonstantin Ananyev	rte_spinlock_t lock;
48703faabfSKonstantin Ananyev	struct mchunk_head chunk;  /* list of chunks */
49703faabfSKonstantin Ananyev} __rte_cache_aligned;
50703faabfSKonstantin Ananyev
51703faabfSKonstantin Ananyevenum {
52703faabfSKonstantin Ananyev	MC_FULL,  /* all memchunk objs are free */
53703faabfSKonstantin Ananyev	MC_USED,  /* some of memchunk objs are allocated */
54703faabfSKonstantin Ananyev	MC_NUM,
55703faabfSKonstantin Ananyev};
56703faabfSKonstantin Ananyev
57703faabfSKonstantin Ananyevstruct memtank {
58703faabfSKonstantin Ananyev	/* user provided data */
59703faabfSKonstantin Ananyev	struct tle_memtank_prm prm;
60703faabfSKonstantin Ananyev
61703faabfSKonstantin Ananyev	/*run-time data */
62703faabfSKonstantin Ananyev	void *raw;		     /* un-aligned ptr returned by alloc() */
63703faabfSKonstantin Ananyev	size_t chunk_size;           /* full size of each memchunk */
64703faabfSKonstantin Ananyev	uint32_t obj_size;	     /* full size of each memobj */
65703faabfSKonstantin Ananyev	uint32_t max_chunk;          /* max allowed number of chunks */
66703faabfSKonstantin Ananyev	uint32_t flags;              /* behavior flags */
67703faabfSKonstantin Ananyev	rte_atomic32_t nb_chunks;    /* number of allocated chunks */
68703faabfSKonstantin Ananyev
69703faabfSKonstantin Ananyev	struct mchunk_list chl[MC_NUM];  /* lists of memchunks */
70703faabfSKonstantin Ananyev
71703faabfSKonstantin Ananyev	struct tle_memtank pub;
72703faabfSKonstantin Ananyev};
73703faabfSKonstantin Ananyev
74703faabfSKonstantin Ananyev/*
75703faabfSKonstantin Ananyev * Obtain pointer to interal memtank struct from public one
76703faabfSKonstantin Ananyev */
77703faabfSKonstantin Ananyevstatic inline struct memtank *
78703faabfSKonstantin Ananyevtank_pub_full(const void *p)
79703faabfSKonstantin Ananyev{
80703faabfSKonstantin Ananyev	uintptr_t v;
81703faabfSKonstantin Ananyev
82703faabfSKonstantin Ananyev	v = (uintptr_t)p - offsetof(struct memtank, pub);
83703faabfSKonstantin Ananyev	return (struct memtank *)v;
84703faabfSKonstantin Ananyev}
85703faabfSKonstantin Ananyev
86703faabfSKonstantin Ananyev/*
87703faabfSKonstantin Ananyev * Obtain pointer to interal memobj struct from public one
88703faabfSKonstantin Ananyev */
89703faabfSKonstantin Ananyevstatic inline struct memobj *
90703faabfSKonstantin Ananyevobj_pub_full(uintptr_t p, uint32_t obj_sz)
91703faabfSKonstantin Ananyev{
92703faabfSKonstantin Ananyev	uintptr_t v;
93703faabfSKonstantin Ananyev
94703faabfSKonstantin Ananyev	v = p + obj_sz - sizeof(struct memobj);
95703faabfSKonstantin Ananyev	return (struct memobj *)v;
96703faabfSKonstantin Ananyev}
97703faabfSKonstantin Ananyev
98703faabfSKonstantin Ananyevstatic inline int
99703faabfSKonstantin Ananyevmemobj_verify(const struct memobj *mo, uint32_t finc)
100703faabfSKonstantin Ananyev{
101703faabfSKonstantin Ananyev	if (mo->red_zone1 != RED_ZONE_V1 || mo->red_zone2 != RED_ZONE_V2 ||
102703faabfSKonstantin Ananyev			mo->dbg.nb_alloc != mo->dbg.nb_free + finc)
103703faabfSKonstantin Ananyev		return -EINVAL;
104703faabfSKonstantin Ananyev	return 0;
105703faabfSKonstantin Ananyev}
106703faabfSKonstantin Ananyev
107703faabfSKonstantin Ananyev#endif	/* _MEMTANK_H_ */