handle non xa_limit_32b ranges in xarray
authorjsg <jsg@openbsd.org>
Mon, 30 Sep 2024 12:21:17 +0000 (12:21 +0000)
committerjsg <jsg@openbsd.org>
Mon, 30 Sep 2024 12:21:17 +0000 (12:21 +0000)
sys/dev/pci/drm/drm_linux.c
sys/dev/pci/drm/include/linux/xarray.h

index b7b26e3..c97c28f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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>
@@ -1003,11 +1003,15 @@ xa_destroy(struct xarray *xa)
 
 /* 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);
@@ -1020,17 +1024,14 @@ __xa_alloc(struct xarray *xa, u32 *id, void *entry, int limit, gfp_t gfp)
        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;
                }
@@ -1046,10 +1047,10 @@ __xa_alloc(struct xarray *xa, u32 *id, void *entry, int limit, gfp_t gfp)
  * 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;
 }
index c41a5fd..fd64305 100644 (file)
@@ -7,9 +7,9 @@
 
 #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:
@@ -29,10 +29,19 @@ struct xarray {
        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);
@@ -41,8 +50,6 @@ void *xa_get_next(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)
@@ -112,11 +119,12 @@ xa_is_err(const void *e)
 }
 
 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;
 }