xref: /openbsd-src/sys/dev/pci/drm/include/linux/xarray.h (revision f84b1df5a16cdd762c93854218de246e79975d3b)
1 /* Public domain. */
2 
3 #ifndef _LINUX_XARRAY_H
4 #define _LINUX_XARRAY_H
5 
6 #include <linux/gfp.h>
7 
8 #include <sys/tree.h>
9 
10 #define XA_FLAGS_ALLOC		1
11 #define XA_FLAGS_ALLOC1		2
12 #define XA_FLAGS_LOCK_IRQ	4
13 
14 /*
15  * lower bits of pointer are tagged:
16  * 00: pointer
17  * 01: value
18  * 10: internal
19  */
20 struct xarray_entry {
21 	SPLAY_ENTRY(xarray_entry) entry;
22 	int id;
23 	void *ptr;
24 };
25 
26 struct xarray {
27 	gfp_t		xa_flags;
28 	struct mutex	xa_lock;
29 	SPLAY_HEAD(xarray_tree, xarray_entry) xa_tree;
30 };
31 
32 void xa_init_flags(struct xarray *, gfp_t);
33 void xa_destroy(struct xarray *);
34 int __xa_alloc(struct xarray *, u32 *, void *, int, gfp_t);
35 void *__xa_load(struct xarray *, unsigned long);
36 void *__xa_store(struct xarray *, unsigned long, void *, gfp_t);
37 void *__xa_erase(struct xarray *, unsigned long);
38 void *xa_get_next(struct xarray *, unsigned long *);
39 
40 #define xa_for_each(xa, index, entry) \
41 	for (index = 0; ((entry) = xa_get_next(xa, &(index))) != NULL; index++)
42 
43 #define xa_limit_32b	0
44 
45 #define xa_lock_irqsave(_xa, _flags) do {		\
46 		_flags = 0;				\
47 		mtx_enter(&(_xa)->xa_lock);		\
48 	} while (0)
49 
50 #define xa_unlock_irqrestore(_xa, _flags) do {		\
51 		(void)(_flags);				\
52 		mtx_leave(&(_xa)->xa_lock);		\
53 	} while (0)
54 
55 static inline void *
56 xa_mk_value(unsigned long v)
57 {
58 	unsigned long r = (v << 1) | 1;
59 	return (void *)r;
60 }
61 
62 static inline bool
63 xa_is_value(const void *e)
64 {
65 	unsigned long v = (unsigned long)e;
66 	return v & 1;
67 }
68 
69 static inline unsigned long
70 xa_to_value(const void *e)
71 {
72 	unsigned long v = (unsigned long)e;
73 	return v >> 1;
74 }
75 
76 #define XA_ERROR(x)	((struct xa_node *)(((unsigned long)x << 2) | 2))
77 
78 static inline int
79 xa_err(const void *e)
80 {
81 	long v = (long)e;
82 	/* not tagged internal, not an errno */
83 	if ((v & 3) != 2)
84 		return 0;
85 	v >>= 2;
86 	if (v >= -ELAST)
87 		return v;
88 	return 0;
89 }
90 
91 static inline bool
92 xa_is_err(const void *e)
93 {
94 	return xa_err(e) != 0;
95 }
96 
97 static inline int
98 xa_alloc(struct xarray *xa, u32 *id, void *entry, int limit, gfp_t gfp)
99 {
100 	int r;
101 	mtx_enter(&xa->xa_lock);
102 	r = __xa_alloc(xa, id, entry, limit, gfp);
103 	mtx_leave(&xa->xa_lock);
104 	return r;
105 }
106 
107 static inline void *
108 xa_load(struct xarray *xa, unsigned long index)
109 {
110 	void *r;
111 	r = __xa_load(xa, index);
112 	return r;
113 }
114 
115 
116 static inline void *
117 xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
118 {
119 	void *r;
120 	mtx_enter(&xa->xa_lock);
121 	r = __xa_store(xa, index, entry, gfp);
122 	mtx_leave(&xa->xa_lock);
123 	return r;
124 }
125 
126 static inline void *
127 xa_erase(struct xarray *xa, unsigned long index)
128 {
129 	void *r;
130 	mtx_enter(&xa->xa_lock);
131 	r = __xa_erase(xa, index);
132 	mtx_leave(&xa->xa_lock);
133 	return r;
134 }
135 
136 static inline void *
137 xa_store_irq(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
138 {
139 	void *r;
140 	mtx_enter(&xa->xa_lock);
141 	r = __xa_store(xa, index, entry, gfp);
142 	mtx_leave(&xa->xa_lock);
143 	return r;
144 }
145 
146 static inline void *
147 xa_erase_irq(struct xarray *xa, unsigned long index)
148 {
149 	void *r;
150 	mtx_enter(&xa->xa_lock);
151 	r = __xa_erase(xa, index);
152 	mtx_leave(&xa->xa_lock);
153 	return r;
154 }
155 
156 static inline bool
157 xa_empty(const struct xarray *xa)
158 {
159 	return SPLAY_EMPTY(&xa->xa_tree);
160 }
161 
162 #endif
163