-/* $OpenBSD: drm_linux.c,v 1.118 2024/09/30 12:09:04 jsg Exp $ */
+/* $OpenBSD: drm_linux.c,v 1.119 2024/09/30 12:21:17 jsg Exp $ */
/*
* Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org>
* Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org>
/* Don't wrap ids. */
int
-__xa_alloc(struct xarray *xa, u32 *id, void *entry, int limit, gfp_t gfp)
+__xa_alloc(struct xarray *xa, u32 *id, void *entry, struct xarray_range xr,
+ gfp_t gfp)
{
struct xarray_entry *xid;
- int start = (xa->xa_flags & XA_FLAGS_ALLOC1) ? 1 : 0;
- int begin;
+ uint32_t start = xr.start;
+ uint32_t end = xr.end;
+
+ if (start == 0 && (xa->xa_flags & XA_FLAGS_ALLOC1))
+ start = 1;
if (gfp & GFP_NOWAIT) {
xid = pool_get(&xa_pool, PR_NOWAIT);
if (xid == NULL)
return -ENOMEM;
- if (limit <= 0)
- limit = INT_MAX;
-
- xid->id = begin = start;
+ xid->id = start;
while (SPLAY_INSERT(xarray_tree, &xa->xa_tree, xid)) {
- if (xid->id == limit)
+ if (xid->id == end)
xid->id = start;
else
xid->id++;
- if (xid->id == begin) {
+ if (xid->id == start) {
pool_put(&xa_pool, xid);
return -EBUSY;
}
* The only caller of this (i915_drm_client.c) doesn't use next id.
*/
int
-__xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry, int limit, u32 *next,
- gfp_t gfp)
+__xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry,
+ struct xarray_range xr, u32 *next, gfp_t gfp)
{
- int r = __xa_alloc(xa, id, entry, limit, gfp);
+ int r = __xa_alloc(xa, id, entry, xr, gfp);
*next = *id + 1;
return r;
}
#include <sys/tree.h>
-#define XA_FLAGS_ALLOC 1
-#define XA_FLAGS_ALLOC1 2
-#define XA_FLAGS_LOCK_IRQ 4
+#define XA_FLAGS_ALLOC (1 << 0)
+#define XA_FLAGS_ALLOC1 (1 << 1)
+#define XA_FLAGS_LOCK_IRQ (1 << 2)
/*
* lower bits of pointer are tagged:
SPLAY_HEAD(xarray_tree, xarray_entry) xa_tree;
};
+struct xarray_range {
+ uint32_t start;
+ uint32_t end;
+};
+
+#define XA_LIMIT(_start, _end) (struct xarray_range){ _start, _end }
+#define xa_limit_32b XA_LIMIT(0, UINT_MAX)
+
void xa_init_flags(struct xarray *, gfp_t);
void xa_destroy(struct xarray *);
-int __xa_alloc(struct xarray *, u32 *, void *, int, gfp_t);
-int __xa_alloc_cyclic(struct xarray *, u32 *, void *, int, u32 *, gfp_t);
+int __xa_alloc(struct xarray *, u32 *, void *, struct xarray_range, gfp_t);
+int __xa_alloc_cyclic(struct xarray *, u32 *, void *, struct xarray_range,
+ u32 *, gfp_t);
void *__xa_load(struct xarray *, unsigned long);
void *__xa_store(struct xarray *, unsigned long, void *, gfp_t);
void *__xa_erase(struct xarray *, unsigned long);
#define xa_for_each(xa, index, entry) \
for (index = 0; ((entry) = xa_get_next(xa, &(index))) != NULL; index++)
-#define xa_limit_32b 0
-
#define xa_lock(_xa) do { \
mtx_enter(&(_xa)->xa_lock); \
} while (0)
}
static inline int
-xa_alloc(struct xarray *xa, u32 *id, void *entry, int limit, gfp_t gfp)
+xa_alloc(struct xarray *xa, u32 *id, void *entry, struct xarray_range xr,
+ gfp_t gfp)
{
int r;
mtx_enter(&xa->xa_lock);
- r = __xa_alloc(xa, id, entry, limit, gfp);
+ r = __xa_alloc(xa, id, entry, xr, gfp);
mtx_leave(&xa->xa_lock);
return r;
}