xref: /openbsd-src/sys/dev/pci/drm/include/linux/xarray.h (revision b73929ac1ec6049ed241c039b31436332c6b3556)
1c349dbc7Sjsg /* Public domain. */
2c349dbc7Sjsg 
3c349dbc7Sjsg #ifndef _LINUX_XARRAY_H
4c349dbc7Sjsg #define _LINUX_XARRAY_H
5c349dbc7Sjsg 
6c349dbc7Sjsg #include <linux/gfp.h>
7c349dbc7Sjsg 
8c349dbc7Sjsg #include <sys/tree.h>
9c349dbc7Sjsg 
1022008fe3Sjsg #define XA_FLAGS_ALLOC		(1 << 0)
1122008fe3Sjsg #define XA_FLAGS_ALLOC1		(1 << 1)
1222008fe3Sjsg #define XA_FLAGS_LOCK_IRQ	(1 << 2)
13c349dbc7Sjsg 
145ca02815Sjsg /*
155ca02815Sjsg  * lower bits of pointer are tagged:
165ca02815Sjsg  * 00: pointer
175ca02815Sjsg  * 01: value
185ca02815Sjsg  * 10: internal
195ca02815Sjsg  */
20c349dbc7Sjsg struct xarray_entry {
21c349dbc7Sjsg 	SPLAY_ENTRY(xarray_entry) entry;
22c349dbc7Sjsg 	int id;
23c349dbc7Sjsg 	void *ptr;
24c349dbc7Sjsg };
25c349dbc7Sjsg 
26c349dbc7Sjsg struct xarray {
27c349dbc7Sjsg 	gfp_t		xa_flags;
285ca02815Sjsg 	struct mutex	xa_lock;
29c349dbc7Sjsg 	SPLAY_HEAD(xarray_tree, xarray_entry) xa_tree;
30c349dbc7Sjsg };
31c349dbc7Sjsg 
32*b73929acSjsg #define DEFINE_XARRAY_ALLOC(name)				\
33*b73929acSjsg 	struct xarray name = {					\
34*b73929acSjsg 		.xa_flags = XA_FLAGS_ALLOC,			\
35*b73929acSjsg 		.xa_lock = MUTEX_INITIALIZER(IPL_NONE),		\
36*b73929acSjsg 		.xa_tree = SPLAY_INITIALIZER(&name.xa_tree)	\
37*b73929acSjsg 	}
38*b73929acSjsg 
3922008fe3Sjsg struct xarray_range {
4022008fe3Sjsg 	uint32_t start;
4122008fe3Sjsg 	uint32_t end;
4222008fe3Sjsg };
4322008fe3Sjsg 
4422008fe3Sjsg #define XA_LIMIT(_start, _end)	(struct xarray_range){ _start, _end }
4522008fe3Sjsg #define xa_limit_32b		XA_LIMIT(0, UINT_MAX)
4622008fe3Sjsg 
47c349dbc7Sjsg void xa_init_flags(struct xarray *, gfp_t);
48c349dbc7Sjsg void xa_destroy(struct xarray *);
4922008fe3Sjsg int __xa_alloc(struct xarray *, u32 *, void *, struct xarray_range, gfp_t);
5022008fe3Sjsg int __xa_alloc_cyclic(struct xarray *, u32 *, void *, struct xarray_range,
5122008fe3Sjsg     u32 *, gfp_t);
525ca02815Sjsg void *__xa_load(struct xarray *, unsigned long);
535ca02815Sjsg void *__xa_store(struct xarray *, unsigned long, void *, gfp_t);
545ca02815Sjsg void *__xa_erase(struct xarray *, unsigned long);
55c349dbc7Sjsg void *xa_get_next(struct xarray *, unsigned long *);
56c349dbc7Sjsg 
57c349dbc7Sjsg #define xa_for_each(xa, index, entry) \
58c349dbc7Sjsg 	for (index = 0; ((entry) = xa_get_next(xa, &(index))) != NULL; index++)
59c349dbc7Sjsg 
601bb76ff1Sjsg #define xa_lock(_xa) do {				\
611bb76ff1Sjsg 		mtx_enter(&(_xa)->xa_lock);		\
621bb76ff1Sjsg 	} while (0)
631bb76ff1Sjsg 
641bb76ff1Sjsg #define xa_unlock(_xa) do {				\
651bb76ff1Sjsg 		mtx_leave(&(_xa)->xa_lock);		\
661bb76ff1Sjsg 	} while (0)
671bb76ff1Sjsg 
681bb76ff1Sjsg #define xa_lock_irq(_xa) do {				\
691bb76ff1Sjsg 		mtx_enter(&(_xa)->xa_lock);		\
701bb76ff1Sjsg 	} while (0)
711bb76ff1Sjsg 
721bb76ff1Sjsg #define xa_unlock_irq(_xa) do {				\
731bb76ff1Sjsg 		mtx_leave(&(_xa)->xa_lock);		\
741bb76ff1Sjsg 	} while (0)
751bb76ff1Sjsg 
765ca02815Sjsg #define xa_lock_irqsave(_xa, _flags) do {		\
775ca02815Sjsg 		_flags = 0;				\
785ca02815Sjsg 		mtx_enter(&(_xa)->xa_lock);		\
795ca02815Sjsg 	} while (0)
805ca02815Sjsg 
815ca02815Sjsg #define xa_unlock_irqrestore(_xa, _flags) do {		\
825ca02815Sjsg 		(void)(_flags);				\
835ca02815Sjsg 		mtx_leave(&(_xa)->xa_lock);		\
845ca02815Sjsg 	} while (0)
855ca02815Sjsg 
86c349dbc7Sjsg static inline void *
87c349dbc7Sjsg xa_mk_value(unsigned long v)
88c349dbc7Sjsg {
89c349dbc7Sjsg 	unsigned long r = (v << 1) | 1;
90c349dbc7Sjsg 	return (void *)r;
91c349dbc7Sjsg }
92c349dbc7Sjsg 
93c349dbc7Sjsg static inline bool
94c349dbc7Sjsg xa_is_value(const void *e)
95c349dbc7Sjsg {
96c349dbc7Sjsg 	unsigned long v = (unsigned long)e;
97c349dbc7Sjsg 	return v & 1;
98c349dbc7Sjsg }
99c349dbc7Sjsg 
100c349dbc7Sjsg static inline unsigned long
101c349dbc7Sjsg xa_to_value(const void *e)
102c349dbc7Sjsg {
103c349dbc7Sjsg 	unsigned long v = (unsigned long)e;
104c349dbc7Sjsg 	return v >> 1;
105c349dbc7Sjsg }
106c349dbc7Sjsg 
1075ca02815Sjsg #define XA_ERROR(x)	((struct xa_node *)(((unsigned long)x << 2) | 2))
1085ca02815Sjsg 
1095ca02815Sjsg static inline int
1105ca02815Sjsg xa_err(const void *e)
1115ca02815Sjsg {
1125ca02815Sjsg 	long v = (long)e;
1135ca02815Sjsg 	/* not tagged internal, not an errno */
1145ca02815Sjsg 	if ((v & 3) != 2)
1155ca02815Sjsg 		return 0;
1165ca02815Sjsg 	v >>= 2;
1175ca02815Sjsg 	if (v >= -ELAST)
1185ca02815Sjsg 		return v;
1195ca02815Sjsg 	return 0;
1205ca02815Sjsg }
1215ca02815Sjsg 
1225ca02815Sjsg static inline bool
1235ca02815Sjsg xa_is_err(const void *e)
1245ca02815Sjsg {
1255ca02815Sjsg 	return xa_err(e) != 0;
1265ca02815Sjsg }
1275ca02815Sjsg 
1285ca02815Sjsg static inline int
12922008fe3Sjsg xa_alloc(struct xarray *xa, u32 *id, void *entry, struct xarray_range xr,
13022008fe3Sjsg     gfp_t gfp)
1315ca02815Sjsg {
1325ca02815Sjsg 	int r;
1335ca02815Sjsg 	mtx_enter(&xa->xa_lock);
13422008fe3Sjsg 	r = __xa_alloc(xa, id, entry, xr, gfp);
1355ca02815Sjsg 	mtx_leave(&xa->xa_lock);
1365ca02815Sjsg 	return r;
1375ca02815Sjsg }
1385ca02815Sjsg 
1395ca02815Sjsg static inline void *
1405ca02815Sjsg xa_load(struct xarray *xa, unsigned long index)
1415ca02815Sjsg {
1425ca02815Sjsg 	void *r;
1435ca02815Sjsg 	r = __xa_load(xa, index);
1445ca02815Sjsg 	return r;
1455ca02815Sjsg }
1465ca02815Sjsg 
1475ca02815Sjsg 
1485ca02815Sjsg static inline void *
1495ca02815Sjsg xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
1505ca02815Sjsg {
1515ca02815Sjsg 	void *r;
1525ca02815Sjsg 	mtx_enter(&xa->xa_lock);
1535ca02815Sjsg 	r = __xa_store(xa, index, entry, gfp);
1545ca02815Sjsg 	mtx_leave(&xa->xa_lock);
1555ca02815Sjsg 	return r;
1565ca02815Sjsg }
1575ca02815Sjsg 
1585ca02815Sjsg static inline void *
1595ca02815Sjsg xa_erase(struct xarray *xa, unsigned long index)
1605ca02815Sjsg {
1615ca02815Sjsg 	void *r;
1625ca02815Sjsg 	mtx_enter(&xa->xa_lock);
1635ca02815Sjsg 	r = __xa_erase(xa, index);
1645ca02815Sjsg 	mtx_leave(&xa->xa_lock);
1655ca02815Sjsg 	return r;
1665ca02815Sjsg }
1675ca02815Sjsg 
1685ca02815Sjsg static inline void *
1695ca02815Sjsg xa_store_irq(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
1705ca02815Sjsg {
1715ca02815Sjsg 	void *r;
1725ca02815Sjsg 	mtx_enter(&xa->xa_lock);
1735ca02815Sjsg 	r = __xa_store(xa, index, entry, gfp);
1745ca02815Sjsg 	mtx_leave(&xa->xa_lock);
1755ca02815Sjsg 	return r;
1765ca02815Sjsg }
1775ca02815Sjsg 
1785ca02815Sjsg static inline void *
1795ca02815Sjsg xa_erase_irq(struct xarray *xa, unsigned long index)
1805ca02815Sjsg {
1815ca02815Sjsg 	void *r;
1825ca02815Sjsg 	mtx_enter(&xa->xa_lock);
1835ca02815Sjsg 	r = __xa_erase(xa, index);
1845ca02815Sjsg 	mtx_leave(&xa->xa_lock);
1855ca02815Sjsg 	return r;
1865ca02815Sjsg }
1875ca02815Sjsg 
1885ca02815Sjsg static inline bool
1895ca02815Sjsg xa_empty(const struct xarray *xa)
1905ca02815Sjsg {
1915ca02815Sjsg 	return SPLAY_EMPTY(&xa->xa_tree);
1925ca02815Sjsg }
1935ca02815Sjsg 
194a8551f48Sjsg static inline void
195a8551f48Sjsg xa_init(struct xarray *xa)
196a8551f48Sjsg {
197a8551f48Sjsg 	xa_init_flags(xa, 0);
198a8551f48Sjsg }
199a8551f48Sjsg 
200c349dbc7Sjsg #endif
201