xref: /dpdk/drivers/net/bnxt/tf_core/bitalloc.h (revision e6e8f03e5459f25153f1e4cd3e9ac30d3e473a61)
1a0dcaea2SMichael Wildt /* SPDX-License-Identifier: BSD-3-Clause
2*e6e8f03eSRandy Schacher  * Copyright(c) 2019-2023 Broadcom
3a0dcaea2SMichael Wildt  * All rights reserved.
4a0dcaea2SMichael Wildt  */
5a0dcaea2SMichael Wildt 
6a0dcaea2SMichael Wildt #ifndef _BITALLOC_H_
7a0dcaea2SMichael Wildt #define _BITALLOC_H_
8a0dcaea2SMichael Wildt 
9a0dcaea2SMichael Wildt #include <stdint.h>
10873661aaSJay Ding #include <stdbool.h>
11a0dcaea2SMichael Wildt 
12a0dcaea2SMichael Wildt /* Bitalloc works on uint32_t as its word size */
13a0dcaea2SMichael Wildt typedef uint32_t bitalloc_word_t;
14a0dcaea2SMichael Wildt 
15a0dcaea2SMichael Wildt struct bitalloc {
16a0dcaea2SMichael Wildt 	bitalloc_word_t size;
17a0dcaea2SMichael Wildt 	bitalloc_word_t free_count;
18a0dcaea2SMichael Wildt 	bitalloc_word_t storage[1];
19a0dcaea2SMichael Wildt };
20a0dcaea2SMichael Wildt 
21a0dcaea2SMichael Wildt #define BA_L0(s) (((s) + 31) / 32)
22a0dcaea2SMichael Wildt #define BA_L1(s) ((BA_L0(s) + 31) / 32)
23a0dcaea2SMichael Wildt #define BA_L2(s) ((BA_L1(s) + 31) / 32)
24a0dcaea2SMichael Wildt #define BA_L3(s) ((BA_L2(s) + 31) / 32)
25a0dcaea2SMichael Wildt #define BA_L4(s) ((BA_L3(s) + 31) / 32)
26a0dcaea2SMichael Wildt 
27a0dcaea2SMichael Wildt #define BITALLOC_SIZEOF(size)                                    \
28a0dcaea2SMichael Wildt 	(sizeof(struct bitalloc) *				 \
29a0dcaea2SMichael Wildt 	 (((sizeof(struct bitalloc) +				 \
30a0dcaea2SMichael Wildt 	    sizeof(struct bitalloc) - 1 +			 \
31a0dcaea2SMichael Wildt 	    (sizeof(bitalloc_word_t) *				 \
32a0dcaea2SMichael Wildt 	     ((BA_L0(size) - 1) +				 \
33a0dcaea2SMichael Wildt 	      ((BA_L0(size) == 1) ? 0 : (BA_L1(size) + 1)) +	 \
34a0dcaea2SMichael Wildt 	      ((BA_L1(size) == 1) ? 0 : (BA_L2(size) + 1)) +	 \
35a0dcaea2SMichael Wildt 	      ((BA_L2(size) == 1) ? 0 : (BA_L3(size) + 1)) +	 \
36a0dcaea2SMichael Wildt 	      ((BA_L3(size) == 1) ? 0 : (BA_L4(size) + 1)))))) / \
37a0dcaea2SMichael Wildt 	  sizeof(struct bitalloc)))
38a0dcaea2SMichael Wildt 
39a0dcaea2SMichael Wildt #define BITALLOC_MAX_SIZE (32 * 32 * 32 * 32 * 32 * 32)
40a0dcaea2SMichael Wildt 
41a0dcaea2SMichael Wildt /* The instantiation of a bitalloc looks a bit odd. Since a
42a0dcaea2SMichael Wildt  * bit allocator has variable storage, we need a way to get a
43a0dcaea2SMichael Wildt  * a pointer to a bitalloc structure that points to the correct
44a0dcaea2SMichael Wildt  * amount of storage. We do this by creating an array of
45a0dcaea2SMichael Wildt  * bitalloc where the first element in the array is the
46a0dcaea2SMichael Wildt  * actual bitalloc base structure, and the remaining elements
47a0dcaea2SMichael Wildt  * in the array provide the storage for it. This approach allows
48a0dcaea2SMichael Wildt  * instances to be individual variables or members of larger
49a0dcaea2SMichael Wildt  * structures.
50a0dcaea2SMichael Wildt  */
51a0dcaea2SMichael Wildt #define BITALLOC_INST(name, size)                      \
52a0dcaea2SMichael Wildt 	struct bitalloc name[(BITALLOC_SIZEOF(size) /  \
53a0dcaea2SMichael Wildt 			      sizeof(struct bitalloc))]
54a0dcaea2SMichael Wildt 
55a0dcaea2SMichael Wildt /* Symbolic return codes */
56a0dcaea2SMichael Wildt #define BA_SUCCESS           0
57a0dcaea2SMichael Wildt #define BA_FAIL             -1
58a0dcaea2SMichael Wildt #define BA_ENTRY_FREE        0
59a0dcaea2SMichael Wildt #define BA_ENTRY_IN_USE      1
60a0dcaea2SMichael Wildt #define BA_NO_ENTRY_FOUND   -1
61a0dcaea2SMichael Wildt 
62a0dcaea2SMichael Wildt /**
631993b267SShahaji Bhosle  * Initializes the bitallocator
64a0dcaea2SMichael Wildt  *
65a0dcaea2SMichael Wildt  * Returns 0 on success, -1 on failure.  Size is arbitrary up to
66a0dcaea2SMichael Wildt  * BITALLOC_MAX_SIZE
67a0dcaea2SMichael Wildt  */
68873661aaSJay Ding int ba_init(struct bitalloc *pool, int size, bool free);
69a0dcaea2SMichael Wildt 
70a0dcaea2SMichael Wildt /**
71a0dcaea2SMichael Wildt  * Returns -1 on failure, or index of allocated entry
72a0dcaea2SMichael Wildt  */
73a0dcaea2SMichael Wildt int ba_alloc(struct bitalloc *pool);
74a0dcaea2SMichael Wildt int ba_alloc_index(struct bitalloc *pool, int index);
75a0dcaea2SMichael Wildt 
76a0dcaea2SMichael Wildt /**
77298dee27SJay Ding  * Returns -1 on failure, or index of allocated entry
78298dee27SJay Ding  */
79298dee27SJay Ding int ba_alloc_reverse(struct bitalloc *pool);
80298dee27SJay Ding 
81298dee27SJay Ding /**
82a0dcaea2SMichael Wildt  * Query a particular index in a pool to check if its in use.
83a0dcaea2SMichael Wildt  *
84a0dcaea2SMichael Wildt  * Returns -1 on invalid index, 1 if the index is allocated, 0 if it
85a0dcaea2SMichael Wildt  * is free
86a0dcaea2SMichael Wildt  */
87a0dcaea2SMichael Wildt int ba_inuse(struct bitalloc *pool, int index);
88a0dcaea2SMichael Wildt 
89a0dcaea2SMichael Wildt /**
90a0dcaea2SMichael Wildt  * Variant of ba_inuse that frees the index if it is allocated, same
91a0dcaea2SMichael Wildt  * return codes as ba_inuse
92a0dcaea2SMichael Wildt  */
93a0dcaea2SMichael Wildt int ba_inuse_free(struct bitalloc *pool, int index);
94a0dcaea2SMichael Wildt 
95a0dcaea2SMichael Wildt /**
96a0dcaea2SMichael Wildt  * Find next index that is in use, start checking at index 'idx'
97a0dcaea2SMichael Wildt  *
98a0dcaea2SMichael Wildt  * Returns next index that is in use on success, or
99a0dcaea2SMichael Wildt  * -1 if no in use index is found
100a0dcaea2SMichael Wildt  */
101a0dcaea2SMichael Wildt int ba_find_next_inuse(struct bitalloc *pool, int idx);
102a0dcaea2SMichael Wildt 
103a0dcaea2SMichael Wildt /**
104a0dcaea2SMichael Wildt  * Variant of ba_find_next_inuse that also frees the next in use index,
105a0dcaea2SMichael Wildt  * same return codes as ba_find_next_inuse
106a0dcaea2SMichael Wildt  */
107a0dcaea2SMichael Wildt int ba_find_next_inuse_free(struct bitalloc *pool, int idx);
108a0dcaea2SMichael Wildt 
109a0dcaea2SMichael Wildt /**
110a0dcaea2SMichael Wildt  * Multiple freeing of the same index has no negative side effects,
111a0dcaea2SMichael Wildt  * but will return -1.  returns -1 on failure, 0 on success.
112a0dcaea2SMichael Wildt  */
113a0dcaea2SMichael Wildt int ba_free(struct bitalloc *pool, int index);
114a0dcaea2SMichael Wildt 
115a0dcaea2SMichael Wildt /**
116a0dcaea2SMichael Wildt  * Returns the pool's free count
117a0dcaea2SMichael Wildt  */
118a0dcaea2SMichael Wildt int ba_free_count(struct bitalloc *pool);
119a0dcaea2SMichael Wildt 
120a0dcaea2SMichael Wildt /**
121a0dcaea2SMichael Wildt  * Returns the pool's in use count
122a0dcaea2SMichael Wildt  */
123a0dcaea2SMichael Wildt int ba_inuse_count(struct bitalloc *pool);
124a0dcaea2SMichael Wildt #endif /* _BITALLOC_H_ */
125