xref: /dpdk/drivers/net/mlx5/mlx5_utils.h (revision a3cf59f56c4745aeaa201bff86cbda02c4deb22e)
18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
2771fa900SAdrien Mazarguil  * Copyright 2015 6WIND S.A.
35feecc57SShahaf Shuler  * Copyright 2015 Mellanox Technologies, Ltd
4771fa900SAdrien Mazarguil  */
5771fa900SAdrien Mazarguil 
6771fa900SAdrien Mazarguil #ifndef RTE_PMD_MLX5_UTILS_H_
7771fa900SAdrien Mazarguil #define RTE_PMD_MLX5_UTILS_H_
8771fa900SAdrien Mazarguil 
9771fa900SAdrien Mazarguil #include <stddef.h>
10b113cb5eSEdward Makarov #include <stdint.h>
11771fa900SAdrien Mazarguil #include <stdio.h>
12771fa900SAdrien Mazarguil #include <limits.h>
13771fa900SAdrien Mazarguil #include <errno.h>
14771fa900SAdrien Mazarguil 
15*a3cf59f5SSuanming Mou #include <rte_spinlock.h>
16*a3cf59f5SSuanming Mou #include <rte_memory.h>
17*a3cf59f5SSuanming Mou #include <rte_bitmap.h>
18*a3cf59f5SSuanming Mou 
197b4f1e6bSMatan Azrad #include <mlx5_common.h>
207b4f1e6bSMatan Azrad 
21771fa900SAdrien Mazarguil #include "mlx5_defs.h"
22771fa900SAdrien Mazarguil 
237b4f1e6bSMatan Azrad 
24725f5dd0SThomas Monjalon /*
25725f5dd0SThomas Monjalon  * Compilation workaround for PPC64 when AltiVec is fully enabled, e.g. std=c11.
26725f5dd0SThomas Monjalon  * Otherwise there would be a type conflict between stdbool and altivec.
27725f5dd0SThomas Monjalon  */
28725f5dd0SThomas Monjalon #if defined(__PPC64__) && !defined(__APPLE_ALTIVEC__)
29725f5dd0SThomas Monjalon #undef bool
30725f5dd0SThomas Monjalon /* redefine as in stdbool.h */
31725f5dd0SThomas Monjalon #define bool _Bool
32725f5dd0SThomas Monjalon #endif
33725f5dd0SThomas Monjalon 
34b113cb5eSEdward Makarov /* Convert a bit number to the corresponding 64-bit mask */
35b113cb5eSEdward Makarov #define MLX5_BITSHIFT(v) (UINT64_C(1) << (v))
36b113cb5eSEdward Makarov 
37771fa900SAdrien Mazarguil /* Save and restore errno around argument evaluation. */
38771fa900SAdrien Mazarguil #define ERRNO_SAFE(x) ((errno = (int []){ errno, ((x), 0) }[0]))
39771fa900SAdrien Mazarguil 
40a170a30dSNélio Laranjeiro extern int mlx5_logtype;
41a170a30dSNélio Laranjeiro 
42771fa900SAdrien Mazarguil /* Generic printf()-like logging macro with automatic line feed. */
43a170a30dSNélio Laranjeiro #define DRV_LOG(level, ...) \
447b4f1e6bSMatan Azrad 	PMD_DRV_LOG_(level, mlx5_logtype, MLX5_DRIVER_NAME, \
45771fa900SAdrien Mazarguil 		__VA_ARGS__ PMD_DRV_LOG_STRIP PMD_DRV_LOG_OPAREN, \
46771fa900SAdrien Mazarguil 		PMD_DRV_LOG_CPAREN)
47771fa900SAdrien Mazarguil 
4880f2d0edSXueming Li #define INFO(...) DRV_LOG(INFO, __VA_ARGS__)
4980f2d0edSXueming Li #define WARN(...) DRV_LOG(WARNING, __VA_ARGS__)
5080f2d0edSXueming Li #define ERROR(...) DRV_LOG(ERR, __VA_ARGS__)
5180f2d0edSXueming Li 
522e22920bSAdrien Mazarguil /* Convenience macros for accessing mbuf fields. */
532e22920bSAdrien Mazarguil #define NEXT(m) ((m)->next)
542e22920bSAdrien Mazarguil #define DATA_LEN(m) ((m)->data_len)
552e22920bSAdrien Mazarguil #define PKT_LEN(m) ((m)->pkt_len)
562e22920bSAdrien Mazarguil #define DATA_OFF(m) ((m)->data_off)
572e22920bSAdrien Mazarguil #define SET_DATA_OFF(m, o) ((m)->data_off = (o))
582e22920bSAdrien Mazarguil #define NB_SEGS(m) ((m)->nb_segs)
592e22920bSAdrien Mazarguil #define PORT(m) ((m)->port)
602e22920bSAdrien Mazarguil 
6167fa62bcSAdrien Mazarguil /* Transpose flags. Useful to convert IBV to DPDK flags. */
6267fa62bcSAdrien Mazarguil #define TRANSPOSE(val, from, to) \
6367fa62bcSAdrien Mazarguil 	(((from) >= (to)) ? \
6467fa62bcSAdrien Mazarguil 	 (((val) & (from)) / ((from) / (to))) : \
6567fa62bcSAdrien Mazarguil 	 (((val) & (from)) * ((to) / (from))))
6667fa62bcSAdrien Mazarguil 
67*a3cf59f5SSuanming Mou /*
68*a3cf59f5SSuanming Mou  * The indexed memory entry index is made up of trunk index and offset of
69*a3cf59f5SSuanming Mou  * the entry in the trunk. Since the entry index is 32 bits, in case user
70*a3cf59f5SSuanming Mou  * prefers to have small trunks, user can change the macro below to a big
71*a3cf59f5SSuanming Mou  * number which helps the pool contains more trunks with lots of entries
72*a3cf59f5SSuanming Mou  * allocated.
73*a3cf59f5SSuanming Mou  */
74*a3cf59f5SSuanming Mou #define TRUNK_IDX_BITS 16
75*a3cf59f5SSuanming Mou #define TRUNK_MAX_IDX ((1 << TRUNK_IDX_BITS) - 1)
76*a3cf59f5SSuanming Mou #define TRUNK_INVALID TRUNK_MAX_IDX
77*a3cf59f5SSuanming Mou #define MLX5_IPOOL_DEFAULT_TRUNK_SIZE (1 << (28 - TRUNK_IDX_BITS))
78*a3cf59f5SSuanming Mou #ifdef RTE_LIBRTE_MLX5_DEBUG
79*a3cf59f5SSuanming Mou #define POOL_DEBUG 1
80*a3cf59f5SSuanming Mou #endif
81*a3cf59f5SSuanming Mou 
82*a3cf59f5SSuanming Mou struct mlx5_indexed_pool_config {
83*a3cf59f5SSuanming Mou 	uint32_t size; /* Pool entry size. */
84*a3cf59f5SSuanming Mou 	uint32_t trunk_size;
85*a3cf59f5SSuanming Mou 	/* Trunk entry number. Must be power of 2. */
86*a3cf59f5SSuanming Mou 	uint32_t need_lock;
87*a3cf59f5SSuanming Mou 	/* Lock is needed for multiple thread usage. */
88*a3cf59f5SSuanming Mou 	const char *type; /* Memory allocate type name. */
89*a3cf59f5SSuanming Mou 	void *(*malloc)(const char *type, size_t size, unsigned int align,
90*a3cf59f5SSuanming Mou 			int socket);
91*a3cf59f5SSuanming Mou 	/* User defined memory allocator. */
92*a3cf59f5SSuanming Mou 	void (*free)(void *addr); /* User defined memory release. */
93*a3cf59f5SSuanming Mou };
94*a3cf59f5SSuanming Mou 
95*a3cf59f5SSuanming Mou struct mlx5_indexed_trunk {
96*a3cf59f5SSuanming Mou 	uint32_t idx; /* Trunk id. */
97*a3cf59f5SSuanming Mou 	uint32_t prev; /* Previous free trunk in free list. */
98*a3cf59f5SSuanming Mou 	uint32_t next; /* Next free trunk in free list. */
99*a3cf59f5SSuanming Mou 	uint32_t free; /* Free entries available */
100*a3cf59f5SSuanming Mou 	struct rte_bitmap *bmp;
101*a3cf59f5SSuanming Mou 	uint8_t data[] __rte_cache_min_aligned; /* Entry data start. */
102*a3cf59f5SSuanming Mou };
103*a3cf59f5SSuanming Mou 
104*a3cf59f5SSuanming Mou struct mlx5_indexed_pool {
105*a3cf59f5SSuanming Mou 	struct mlx5_indexed_pool_config cfg; /* Indexed pool configuration. */
106*a3cf59f5SSuanming Mou 	rte_spinlock_t lock; /* Pool lock for multiple thread usage. */
107*a3cf59f5SSuanming Mou 	uint32_t n_trunk_valid; /* Trunks allocated. */
108*a3cf59f5SSuanming Mou 	uint32_t n_trunk; /* Trunk pointer array size. */
109*a3cf59f5SSuanming Mou 	/* Dim of trunk pointer array. */
110*a3cf59f5SSuanming Mou 	struct mlx5_indexed_trunk **trunks;
111*a3cf59f5SSuanming Mou 	uint32_t free_list; /* Index to first free trunk. */
112*a3cf59f5SSuanming Mou #ifdef POOL_DEBUG
113*a3cf59f5SSuanming Mou 	uint32_t n_entry;
114*a3cf59f5SSuanming Mou 	uint32_t trunk_new;
115*a3cf59f5SSuanming Mou 	uint32_t trunk_avail;
116*a3cf59f5SSuanming Mou 	uint32_t trunk_empty;
117*a3cf59f5SSuanming Mou 	uint32_t trunk_free;
118*a3cf59f5SSuanming Mou #endif
119*a3cf59f5SSuanming Mou };
120*a3cf59f5SSuanming Mou 
121634efbc2SNelio Laranjeiro /**
12246287eacSBing Zhao  * Return logarithm of the nearest power of two above input value.
123634efbc2SNelio Laranjeiro  *
124634efbc2SNelio Laranjeiro  * @param v
125634efbc2SNelio Laranjeiro  *   Input value.
126634efbc2SNelio Laranjeiro  *
127634efbc2SNelio Laranjeiro  * @return
12846287eacSBing Zhao  *   Logarithm of the nearest power of two above input value.
129634efbc2SNelio Laranjeiro  */
130634efbc2SNelio Laranjeiro static inline unsigned int
131634efbc2SNelio Laranjeiro log2above(unsigned int v)
132634efbc2SNelio Laranjeiro {
133634efbc2SNelio Laranjeiro 	unsigned int l;
134634efbc2SNelio Laranjeiro 	unsigned int r;
135634efbc2SNelio Laranjeiro 
136634efbc2SNelio Laranjeiro 	for (l = 0, r = 0; (v >> 1); ++l, v >>= 1)
137634efbc2SNelio Laranjeiro 		r |= (v & 1);
138693f715dSHuawei Xie 	return l + r;
139634efbc2SNelio Laranjeiro }
140634efbc2SNelio Laranjeiro 
14146287eacSBing Zhao /** Maximum size of string for naming the hlist table. */
14246287eacSBing Zhao #define MLX5_HLIST_NAMESIZE			32
14346287eacSBing Zhao 
14446287eacSBing Zhao /**
14546287eacSBing Zhao  * Structure of the entry in the hash list, user should define its own struct
14646287eacSBing Zhao  * that contains this in order to store the data. The 'key' is 64-bits right
14746287eacSBing Zhao  * now and its user's responsibility to guarantee there is no collision.
14846287eacSBing Zhao  */
14946287eacSBing Zhao struct mlx5_hlist_entry {
15046287eacSBing Zhao 	LIST_ENTRY(mlx5_hlist_entry) next; /* entry pointers in the list. */
15146287eacSBing Zhao 	uint64_t key; /* user defined 'key', could be the hash signature. */
15246287eacSBing Zhao };
15346287eacSBing Zhao 
15446287eacSBing Zhao /** Structure for hash head. */
15546287eacSBing Zhao LIST_HEAD(mlx5_hlist_head, mlx5_hlist_entry);
15646287eacSBing Zhao 
15746287eacSBing Zhao /** Type of function that is used to handle the data before freeing. */
15846287eacSBing Zhao typedef void (*mlx5_hlist_destroy_callback_fn)(void *p, void *ctx);
15946287eacSBing Zhao 
16046287eacSBing Zhao /** hash list table structure */
16146287eacSBing Zhao struct mlx5_hlist {
16246287eacSBing Zhao 	char name[MLX5_HLIST_NAMESIZE]; /**< Name of the hash list. */
16346287eacSBing Zhao 	/**< number of heads, need to be power of 2. */
16446287eacSBing Zhao 	uint32_t table_sz;
16546287eacSBing Zhao 	/**< mask to get the index of the list heads. */
16646287eacSBing Zhao 	uint32_t mask;
16746287eacSBing Zhao 	struct mlx5_hlist_head heads[];	/**< list head arrays. */
16846287eacSBing Zhao };
16946287eacSBing Zhao 
17046287eacSBing Zhao /**
17146287eacSBing Zhao  * Create a hash list table, the user can specify the list heads array size
17246287eacSBing Zhao  * of the table, now the size should be a power of 2 in order to get better
17346287eacSBing Zhao  * distribution for the entries. Each entry is a part of the whole data element
17446287eacSBing Zhao  * and the caller should be responsible for the data element's allocation and
17546287eacSBing Zhao  * cleanup / free. Key of each entry will be calculated with CRC in order to
17646287eacSBing Zhao  * generate a little fairer distribution.
17746287eacSBing Zhao  *
17846287eacSBing Zhao  * @param name
17946287eacSBing Zhao  *   Name of the hash list(optional).
18046287eacSBing Zhao  * @param size
18146287eacSBing Zhao  *   Heads array size of the hash list.
18246287eacSBing Zhao  *
18346287eacSBing Zhao  * @return
18446287eacSBing Zhao  *   Pointer of the hash list table created, NULL on failure.
18546287eacSBing Zhao  */
18646287eacSBing Zhao struct mlx5_hlist *mlx5_hlist_create(const char *name, uint32_t size);
18746287eacSBing Zhao 
18846287eacSBing Zhao /**
18946287eacSBing Zhao  * Search an entry matching the key.
19046287eacSBing Zhao  *
19146287eacSBing Zhao  * @param h
19246287eacSBing Zhao  *   Pointer to the hast list table.
19346287eacSBing Zhao  * @param key
19446287eacSBing Zhao  *   Key for the searching entry.
19546287eacSBing Zhao  *
19646287eacSBing Zhao  * @return
19746287eacSBing Zhao  *   Pointer of the hlist entry if found, NULL otherwise.
19846287eacSBing Zhao  */
19946287eacSBing Zhao struct mlx5_hlist_entry *mlx5_hlist_lookup(struct mlx5_hlist *h, uint64_t key);
20046287eacSBing Zhao 
20146287eacSBing Zhao /**
20246287eacSBing Zhao  * Insert an entry to the hash list table, the entry is only part of whole data
20346287eacSBing Zhao  * element and a 64B key is used for matching. User should construct the key or
20446287eacSBing Zhao  * give a calculated hash signature and guarantee there is no collision.
20546287eacSBing Zhao  *
20646287eacSBing Zhao  * @param h
20746287eacSBing Zhao  *   Pointer to the hast list table.
20846287eacSBing Zhao  * @param entry
20946287eacSBing Zhao  *   Entry to be inserted into the hash list table.
21046287eacSBing Zhao  *
21146287eacSBing Zhao  * @return
21246287eacSBing Zhao  *   - zero for success.
21346287eacSBing Zhao  *   - -EEXIST if the entry is already inserted.
21446287eacSBing Zhao  */
21546287eacSBing Zhao int mlx5_hlist_insert(struct mlx5_hlist *h, struct mlx5_hlist_entry *entry);
21646287eacSBing Zhao 
21746287eacSBing Zhao /**
21846287eacSBing Zhao  * Remove an entry from the hash list table. User should guarantee the validity
21946287eacSBing Zhao  * of the entry.
22046287eacSBing Zhao  *
22146287eacSBing Zhao  * @param h
22246287eacSBing Zhao  *   Pointer to the hast list table. (not used)
22346287eacSBing Zhao  * @param entry
22446287eacSBing Zhao  *   Entry to be removed from the hash list table.
22546287eacSBing Zhao  */
22646287eacSBing Zhao void mlx5_hlist_remove(struct mlx5_hlist *h __rte_unused,
22746287eacSBing Zhao 		       struct mlx5_hlist_entry *entry);
22846287eacSBing Zhao 
22946287eacSBing Zhao /**
23046287eacSBing Zhao  * Destroy the hash list table, all the entries already inserted into the lists
23146287eacSBing Zhao  * will be handled by the callback function provided by the user (including
23246287eacSBing Zhao  * free if needed) before the table is freed.
23346287eacSBing Zhao  *
23446287eacSBing Zhao  * @param h
23546287eacSBing Zhao  *   Pointer to the hast list table.
23646287eacSBing Zhao  * @param cb
23746287eacSBing Zhao  *   Callback function for each inserted entry when destroying the hash list.
23846287eacSBing Zhao  * @param ctx
23946287eacSBing Zhao  *   Common context parameter used by callback function for each entry.
24046287eacSBing Zhao  */
24146287eacSBing Zhao void mlx5_hlist_destroy(struct mlx5_hlist *h,
24246287eacSBing Zhao 			mlx5_hlist_destroy_callback_fn cb, void *ctx);
24346287eacSBing Zhao 
244*a3cf59f5SSuanming Mou /**
245*a3cf59f5SSuanming Mou  * This function allocates non-initialized memory entry from pool.
246*a3cf59f5SSuanming Mou  * In NUMA systems, the memory entry allocated resides on the same
247*a3cf59f5SSuanming Mou  * NUMA socket as the core that calls this function.
248*a3cf59f5SSuanming Mou  *
249*a3cf59f5SSuanming Mou  * Memory entry is allocated from memory trunk, no alignment.
250*a3cf59f5SSuanming Mou  *
251*a3cf59f5SSuanming Mou  * @param pool
252*a3cf59f5SSuanming Mou  *   Pointer to indexed memory entry pool.
253*a3cf59f5SSuanming Mou  *   No initialization required.
254*a3cf59f5SSuanming Mou  * @param[out] idx
255*a3cf59f5SSuanming Mou  *   Pointer to memory to save allocated index.
256*a3cf59f5SSuanming Mou  *   Memory index always positive value.
257*a3cf59f5SSuanming Mou  * @return
258*a3cf59f5SSuanming Mou  *   - Pointer to the allocated memory entry.
259*a3cf59f5SSuanming Mou  *   - NULL on error. Not enough memory, or invalid arguments.
260*a3cf59f5SSuanming Mou  */
261*a3cf59f5SSuanming Mou void *mlx5_ipool_malloc(struct mlx5_indexed_pool *pool, uint32_t *idx);
262*a3cf59f5SSuanming Mou 
263*a3cf59f5SSuanming Mou /**
264*a3cf59f5SSuanming Mou  * This function allocates zero initialized memory entry from pool.
265*a3cf59f5SSuanming Mou  * In NUMA systems, the memory entry allocated resides on the same
266*a3cf59f5SSuanming Mou  * NUMA socket as the core that calls this function.
267*a3cf59f5SSuanming Mou  *
268*a3cf59f5SSuanming Mou  * Memory entry is allocated from memory trunk, no alignment.
269*a3cf59f5SSuanming Mou  *
270*a3cf59f5SSuanming Mou  * @param pool
271*a3cf59f5SSuanming Mou  *   Pointer to indexed memory pool.
272*a3cf59f5SSuanming Mou  *   No initialization required.
273*a3cf59f5SSuanming Mou  * @param[out] idx
274*a3cf59f5SSuanming Mou  *   Pointer to memory to save allocated index.
275*a3cf59f5SSuanming Mou  *   Memory index always positive value.
276*a3cf59f5SSuanming Mou  * @return
277*a3cf59f5SSuanming Mou  *   - Pointer to the allocated memory entry .
278*a3cf59f5SSuanming Mou  *   - NULL on error. Not enough memory, or invalid arguments.
279*a3cf59f5SSuanming Mou  */
280*a3cf59f5SSuanming Mou void *mlx5_ipool_zmalloc(struct mlx5_indexed_pool *pool, uint32_t *idx);
281*a3cf59f5SSuanming Mou 
282*a3cf59f5SSuanming Mou /**
283*a3cf59f5SSuanming Mou  * This function frees indexed memory entry to pool.
284*a3cf59f5SSuanming Mou  * Caller has to make sure that the index is allocated from same pool.
285*a3cf59f5SSuanming Mou  *
286*a3cf59f5SSuanming Mou  * @param pool
287*a3cf59f5SSuanming Mou  *   Pointer to indexed memory pool.
288*a3cf59f5SSuanming Mou  * @param idx
289*a3cf59f5SSuanming Mou  *   Allocated memory entry index.
290*a3cf59f5SSuanming Mou  */
291*a3cf59f5SSuanming Mou void mlx5_ipool_free(struct mlx5_indexed_pool *pool, uint32_t idx);
292*a3cf59f5SSuanming Mou 
293*a3cf59f5SSuanming Mou /**
294*a3cf59f5SSuanming Mou  * This function returns pointer of indexed memory entry from index.
295*a3cf59f5SSuanming Mou  * Caller has to make sure that the index is valid, and allocated
296*a3cf59f5SSuanming Mou  * from same pool.
297*a3cf59f5SSuanming Mou  *
298*a3cf59f5SSuanming Mou  * @param pool
299*a3cf59f5SSuanming Mou  *   Pointer to indexed memory pool.
300*a3cf59f5SSuanming Mou  * @param idx
301*a3cf59f5SSuanming Mou  *   Allocated memory index.
302*a3cf59f5SSuanming Mou  * @return
303*a3cf59f5SSuanming Mou  *   - Pointer to indexed memory entry.
304*a3cf59f5SSuanming Mou  */
305*a3cf59f5SSuanming Mou void *mlx5_ipool_get(struct mlx5_indexed_pool *pool, uint32_t idx);
306*a3cf59f5SSuanming Mou 
307*a3cf59f5SSuanming Mou /**
308*a3cf59f5SSuanming Mou  * This function creates indexed memory pool.
309*a3cf59f5SSuanming Mou  * Caller has to configure the configuration accordingly.
310*a3cf59f5SSuanming Mou  *
311*a3cf59f5SSuanming Mou  * @param pool
312*a3cf59f5SSuanming Mou  *   Pointer to indexed memory pool.
313*a3cf59f5SSuanming Mou  * @param cfg
314*a3cf59f5SSuanming Mou  *   Allocated memory index.
315*a3cf59f5SSuanming Mou  */
316*a3cf59f5SSuanming Mou struct mlx5_indexed_pool *
317*a3cf59f5SSuanming Mou mlx5_ipool_create(struct mlx5_indexed_pool_config *cfg);
318*a3cf59f5SSuanming Mou 
319*a3cf59f5SSuanming Mou /**
320*a3cf59f5SSuanming Mou  * This function releases all resources of pool.
321*a3cf59f5SSuanming Mou  * Caller has to make sure that all indexes and memories allocated
322*a3cf59f5SSuanming Mou  * from this pool not referenced anymore.
323*a3cf59f5SSuanming Mou  *
324*a3cf59f5SSuanming Mou  * @param pool
325*a3cf59f5SSuanming Mou  *   Pointer to indexed memory pool.
326*a3cf59f5SSuanming Mou  * @return
327*a3cf59f5SSuanming Mou  *   - non-zero value on error.
328*a3cf59f5SSuanming Mou  *   - 0 on success.
329*a3cf59f5SSuanming Mou  */
330*a3cf59f5SSuanming Mou int mlx5_ipool_destroy(struct mlx5_indexed_pool *pool);
331*a3cf59f5SSuanming Mou 
332*a3cf59f5SSuanming Mou /**
333*a3cf59f5SSuanming Mou  * This function dumps debug info of pool.
334*a3cf59f5SSuanming Mou  *
335*a3cf59f5SSuanming Mou  * @param pool
336*a3cf59f5SSuanming Mou  *   Pointer to indexed memory pool.
337*a3cf59f5SSuanming Mou  */
338*a3cf59f5SSuanming Mou void mlx5_ipool_dump(struct mlx5_indexed_pool *pool);
339*a3cf59f5SSuanming Mou 
340*a3cf59f5SSuanming Mou /*
341*a3cf59f5SSuanming Mou  * Macros for linked list based on indexed memory.
342*a3cf59f5SSuanming Mou  * Example data structure:
343*a3cf59f5SSuanming Mou  * struct Foo {
344*a3cf59f5SSuanming Mou  *	ILIST_ENTRY(uint16_t) next;
345*a3cf59f5SSuanming Mou  *	...
346*a3cf59f5SSuanming Mou  * }
347*a3cf59f5SSuanming Mou  *
348*a3cf59f5SSuanming Mou  */
349*a3cf59f5SSuanming Mou #define ILIST_ENTRY(type)						\
350*a3cf59f5SSuanming Mou struct {								\
351*a3cf59f5SSuanming Mou 	type prev; /* Index of previous element. */			\
352*a3cf59f5SSuanming Mou 	type next; /* Index of next element. */				\
353*a3cf59f5SSuanming Mou }
354*a3cf59f5SSuanming Mou 
355*a3cf59f5SSuanming Mou #define ILIST_INSERT(pool, head, idx, elem, field)			\
356*a3cf59f5SSuanming Mou 	do {								\
357*a3cf59f5SSuanming Mou 		typeof(elem) peer;					\
358*a3cf59f5SSuanming Mou 		MLX5_ASSERT((elem) && (idx));				\
359*a3cf59f5SSuanming Mou 		(elem)->field.next = *(head);				\
360*a3cf59f5SSuanming Mou 		(elem)->field.prev = 0;					\
361*a3cf59f5SSuanming Mou 		if (*(head)) {						\
362*a3cf59f5SSuanming Mou 			(peer) = mlx5_ipool_get(pool, *(head));		\
363*a3cf59f5SSuanming Mou 			if (peer)					\
364*a3cf59f5SSuanming Mou 				(peer)->field.prev = (idx);		\
365*a3cf59f5SSuanming Mou 		}							\
366*a3cf59f5SSuanming Mou 		*(head) = (idx);					\
367*a3cf59f5SSuanming Mou 	} while (0)
368*a3cf59f5SSuanming Mou 
369*a3cf59f5SSuanming Mou #define ILIST_REMOVE(pool, head, idx, elem, field)			\
370*a3cf59f5SSuanming Mou 	do {								\
371*a3cf59f5SSuanming Mou 		typeof(elem) peer;					\
372*a3cf59f5SSuanming Mou 		MLX5_ASSERT(elem);					\
373*a3cf59f5SSuanming Mou 		MLX5_ASSERT(head);					\
374*a3cf59f5SSuanming Mou 		if ((elem)->field.prev) {				\
375*a3cf59f5SSuanming Mou 			(peer) = mlx5_ipool_get				\
376*a3cf59f5SSuanming Mou 				 (pool, (elem)->field.prev);		\
377*a3cf59f5SSuanming Mou 			if (peer)					\
378*a3cf59f5SSuanming Mou 				(peer)->field.next = (elem)->field.next;\
379*a3cf59f5SSuanming Mou 		}							\
380*a3cf59f5SSuanming Mou 		if ((elem)->field.next) {				\
381*a3cf59f5SSuanming Mou 			(peer) = mlx5_ipool_get				\
382*a3cf59f5SSuanming Mou 				 (pool, (elem)->field.next);		\
383*a3cf59f5SSuanming Mou 			if (peer)					\
384*a3cf59f5SSuanming Mou 				(peer)->field.prev = (elem)->field.prev;\
385*a3cf59f5SSuanming Mou 		}							\
386*a3cf59f5SSuanming Mou 		if (*(head) == (idx))					\
387*a3cf59f5SSuanming Mou 			*(head) = (elem)->field.next;			\
388*a3cf59f5SSuanming Mou 	} while (0)
389*a3cf59f5SSuanming Mou 
390*a3cf59f5SSuanming Mou #define ILIST_FOREACH(pool, head, idx, elem, field)			\
391*a3cf59f5SSuanming Mou 	for ((idx) = (head), (elem) =					\
392*a3cf59f5SSuanming Mou 	     (idx) ? mlx5_ipool_get(pool, (idx)) : NULL; (elem);	\
393*a3cf59f5SSuanming Mou 	     idx = (elem)->field.next, (elem) =				\
394*a3cf59f5SSuanming Mou 	     (idx) ? mlx5_ipool_get(pool, idx) : NULL)
395*a3cf59f5SSuanming Mou 
396*a3cf59f5SSuanming Mou /* Single index list. */
397*a3cf59f5SSuanming Mou #define SILIST_ENTRY(type)						\
398*a3cf59f5SSuanming Mou struct {								\
399*a3cf59f5SSuanming Mou 	type next; /* Index of next element. */				\
400*a3cf59f5SSuanming Mou }
401*a3cf59f5SSuanming Mou 
402*a3cf59f5SSuanming Mou #define SILIST_INSERT(head, idx, elem, field)				\
403*a3cf59f5SSuanming Mou 	do {								\
404*a3cf59f5SSuanming Mou 		MLX5_ASSERT((elem) && (idx));				\
405*a3cf59f5SSuanming Mou 		(elem)->field.next = *(head);				\
406*a3cf59f5SSuanming Mou 		*(head) = (idx);					\
407*a3cf59f5SSuanming Mou 	} while (0)
408*a3cf59f5SSuanming Mou 
409*a3cf59f5SSuanming Mou #define SILIST_FOREACH(pool, head, idx, elem, field)			\
410*a3cf59f5SSuanming Mou 	for ((idx) = (head), (elem) =					\
411*a3cf59f5SSuanming Mou 	     (idx) ? mlx5_ipool_get(pool, (idx)) : NULL; (elem);	\
412*a3cf59f5SSuanming Mou 	     idx = (elem)->field.next, (elem) =				\
413*a3cf59f5SSuanming Mou 	     (idx) ? mlx5_ipool_get(pool, idx) : NULL)
414*a3cf59f5SSuanming Mou 
415771fa900SAdrien Mazarguil #endif /* RTE_PMD_MLX5_UTILS_H_ */
416