From 321c78384ee14fa8641d6ee0d556dd4286b69b7c Mon Sep 17 00:00:00 2001 From: jsg Date: Tue, 7 Apr 2026 09:11:15 +0000 Subject: [PATCH] add idr_alloc_cyclic() for 6.18.21 drm --- sys/dev/pci/drm/drm_linux.c | 41 ++++++++++++++++++++++++++++- sys/dev/pci/drm/include/linux/idr.h | 5 +++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/sys/dev/pci/drm/drm_linux.c b/sys/dev/pci/drm/drm_linux.c index 2cad5cf4f0b..a96342d2f4a 100644 --- a/sys/dev/pci/drm/drm_linux.c +++ b/sys/dev/pci/drm/drm_linux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: drm_linux.c,v 1.134 2026/03/31 08:54:14 jsg Exp $ */ +/* $OpenBSD: drm_linux.c,v 1.135 2026/04/07 09:11:15 jsg Exp $ */ /* * Copyright (c) 2013 Jonathan Gray * Copyright (c) 2015, 2016 Mark Kettenis @@ -810,6 +810,7 @@ void idr_init(struct idr *idr) { SPLAY_INIT(&idr->tree); + idr->next = 0; } void @@ -867,6 +868,44 @@ idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask) return id->id; } +/* [start, end) */ +int +idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask) +{ + int flags = (gfp_mask & GFP_NOWAIT) ? PR_NOWAIT : PR_WAITOK; + struct idr_entry *id; + + KERNEL_ASSERT_LOCKED(); + + if (idr_entry_cache) { + id = idr_entry_cache; + idr_entry_cache = NULL; + } else { + id = pool_get(&idr_pool, flags); + if (id == NULL) + return -ENOMEM; + } + + if (end <= 0) + end = INT_MAX; + + id->id = idr->next; + while (SPLAY_INSERT(idr_tree, &idr->tree, id)) { + id->id++; + if (id->id == end) { + id->id = start; + } else if (id->id == idr->next) { + pool_put(&idr_pool, id); + return -ENOSPC; + } + } + id->ptr = ptr; + idr->next = id->id + 1; + if (idr->next == end) + idr->next = start; + return id->id; +} + void * idr_replace(struct idr *idr, void *ptr, unsigned long id) { diff --git a/sys/dev/pci/drm/include/linux/idr.h b/sys/dev/pci/drm/include/linux/idr.h index 169f326dc25..c39f568282f 100644 --- a/sys/dev/pci/drm/include/linux/idr.h +++ b/sys/dev/pci/drm/include/linux/idr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: idr.h,v 1.9 2026/04/07 09:04:16 jsg Exp $ */ +/* $OpenBSD: idr.h,v 1.10 2026/04/07 09:11:15 jsg Exp $ */ /* * Copyright (c) 2016 Mark Kettenis * @@ -31,16 +31,19 @@ struct idr_entry { struct idr { SPLAY_HEAD(idr_tree, idr_entry) tree; + unsigned long next; }; #define DEFINE_IDR(name) \ struct idr name = { \ .tree = SPLAY_INITIALIZER(&name.idr.tree), \ + .next = 0 \ } void idr_init(struct idr *); void idr_preload(unsigned int); int idr_alloc(struct idr *, void *, int, int, gfp_t); +int idr_alloc_cyclic(struct idr *, void *, int, int, gfp_t); void *idr_find(struct idr *, unsigned long); void *idr_replace(struct idr *, void *, unsigned long); void *idr_remove(struct idr *, unsigned long);