Module Name: src Committed By: riastradh Date: Sun Dec 19 11:51:07 UTC 2021
Modified Files: src/sys/external/bsd/drm2/include/linux: xarray.h src/sys/external/bsd/drm2/linux: files.drmkms_linux Added Files: src/sys/external/bsd/drm2/linux: linux_xa.c Log Message: linux: Draft half-arsed xarray shims To generate a diff of this commit: cvs rdiff -u -r1.7 -r1.8 src/sys/external/bsd/drm2/include/linux/xarray.h cvs rdiff -u -r1.35 -r1.36 src/sys/external/bsd/drm2/linux/files.drmkms_linux cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/linux/linux_xa.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/include/linux/xarray.h diff -u src/sys/external/bsd/drm2/include/linux/xarray.h:1.7 src/sys/external/bsd/drm2/include/linux/xarray.h:1.8 --- src/sys/external/bsd/drm2/include/linux/xarray.h:1.7 Sun Dec 19 11:50:47 2021 +++ src/sys/external/bsd/drm2/include/linux/xarray.h Sun Dec 19 11:51:07 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: xarray.h,v 1.7 2021/12/19 11:50:47 riastradh Exp $ */ +/* $NetBSD: xarray.h,v 1.8 2021/12/19 11:51:07 riastradh Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -36,22 +36,34 @@ struct xarray; struct xa_limit; +struct xa_limit { + uint32_t max; + uint32_t min; +}; + struct xarray { kmutex_t xa_lock; struct radix_tree xa_tree; gfp_t xa_gfp; }; -struct xa_limit { - uint32_t max; - uint32_t min; -}; - #define xa_for_each(XA, INDEX, ENTRY) \ - for ((INDEX) = 0, (ENTRY) = xa_find((XA), &(INDEX), ULONG_MAX, 0); \ + for ((INDEX) = 0, (ENTRY) = xa_find((XA), &(INDEX), ULONG_MAX, -1); \ (ENTRY) != NULL; \ (ENTRY) = xa_find_after((XA), &(INDEX), ULONG_MAX, 0)) +#define XA_ERROR(error) ((void *)(((uintptr_t)error << 2) | 2)) + +static inline int +xa_err(void *cookie) +{ + + if (((uintptr_t)cookie & 3) != 2) + return 0; + + return (uintptr_t)cookie >> 2; +} + #define XA_FLAGS_ALLOC 0 #define xa_alloc linux_xa_alloc Index: src/sys/external/bsd/drm2/linux/files.drmkms_linux diff -u src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.35 src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.36 --- src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.35 Sun Dec 19 11:50:09 2021 +++ src/sys/external/bsd/drm2/linux/files.drmkms_linux Sun Dec 19 11:51:07 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.drmkms_linux,v 1.35 2021/12/19 11:50:09 riastradh Exp $ +# $NetBSD: files.drmkms_linux,v 1.36 2021/12/19 11:51:07 riastradh Exp $ define drmkms_linux: i2cexec, i2c_bitbang @@ -30,3 +30,4 @@ file external/bsd/drm2/linux/linux_sync_ file external/bsd/drm2/linux/linux_wait_bit.c drmkms_linux file external/bsd/drm2/linux/linux_writecomb.c drmkms_linux file external/bsd/drm2/linux/linux_ww_mutex.c drmkms_linux +file external/bsd/drm2/linux/linux_xa.c drmkms_linux Added files: Index: src/sys/external/bsd/drm2/linux/linux_xa.c diff -u /dev/null src/sys/external/bsd/drm2/linux/linux_xa.c:1.1 --- /dev/null Sun Dec 19 11:51:07 2021 +++ src/sys/external/bsd/drm2/linux/linux_xa.c Sun Dec 19 11:51:07 2021 @@ -0,0 +1,181 @@ +/* $NetBSD: linux_xa.c,v 1.1 2021/12/19 11:51:07 riastradh Exp $ */ + +/*- + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: linux_xa.c,v 1.1 2021/12/19 11:51:07 riastradh Exp $"); + +#include <sys/radixtree.h> + +#include <uvm/uvm_pdaemon.h> + +#include <linux/xarray.h> + +const struct xa_limit xa_limit_32b = { .min = 0, .max = UINT32_MAX }; + +void +xa_init_flags(struct xarray *xa, gfp_t gfp) +{ + + mutex_init(&xa->xa_lock, MUTEX_DEFAULT, IPL_VM); + radix_tree_init_tree(&xa->xa_tree); + xa->xa_gfp = gfp; +} + +void +xa_destroy(struct xarray *xa) +{ + + KASSERT(radix_tree_empty_tree_p(&xa->xa_tree)); + radix_tree_fini_tree(&xa->xa_tree); + mutex_destroy(&xa->xa_lock); +} + +void * +xa_load(struct xarray *xa, unsigned long key) +{ + void *datum; + + /* XXX pserialize */ + mutex_enter(&xa->xa_lock); + datum = radix_tree_lookup_node(&xa->xa_tree, key); + mutex_exit(&xa->xa_lock); + + return datum; +} + +void * +xa_store(struct xarray *xa, unsigned long key, void *datum, gfp_t gfp) +{ + void *collision; + int error; + + KASSERT(datum != NULL); + KASSERT(((uintptr_t)datum & 0x3) == 0); + +retry: mutex_enter(&xa->xa_lock); + collision = radix_tree_lookup_node(&xa->xa_tree, key); + error = radix_tree_insert_node(&xa->xa_tree, key, datum); + mutex_exit(&xa->xa_lock); + if (error) { + if (gfp & __GFP_WAIT) { + uvm_wait("xa"); + goto retry; + } + /* XXX errno NetBSD->Linux */ + return XA_ERROR(-error); + } + + return collision; +} + +int +xa_alloc(struct xarray *xa, uint32_t *idp, void *datum, struct xa_limit limit, + gfp_t gfp) +{ + uint32_t key = limit.min; + void *collision; + int error; + + KASSERTMSG(limit.min < limit.max, "min=%"PRIu32" max=%"PRIu32, + limit.min, limit.max); + +retry: mutex_enter(&xa->xa_lock); + /* XXX use the radix tree to make this fast */ + while ((collision = radix_tree_lookup_node(&xa->xa_tree, key)) + != NULL) { + if (key++ == limit.max) + goto out; + } + error = radix_tree_insert_node(&xa->xa_tree, key, datum); +out: mutex_exit(&xa->xa_lock); + + if (collision) + return -EBUSY; + if (error) { + if (gfp & __GFP_WAIT) { + uvm_wait("xa"); + goto retry; + } + /* XXX errno NetBSD->Linux */ + return -error; + } + + /* Success! */ + *idp = key; + return 0; +} + +void * +xa_find(struct xarray *xa, unsigned long *startp, unsigned long max, + unsigned tagmask) +{ + uint64_t key = *startp; + void *candidate = NULL; + + mutex_enter(&xa->xa_lock); + for (; key < max; key++, candidate = NULL) { + candidate = radix_tree_lookup_node(&xa->xa_tree, key); + if (candidate == NULL) + continue; + if (tagmask == -1 || + radix_tree_get_tag(&xa->xa_tree, key, tagmask)) + break; + } + mutex_exit(&xa->xa_lock); + + if (candidate) + *startp = key; + return candidate; +} + +void * +xa_find_after(struct xarray *xa, unsigned long *startp, unsigned long max, + unsigned tagmask) +{ + unsigned long start = *startp; + void *found; + + if (start == max) + return NULL; + found = xa_find(xa, &start, max, tagmask); + if (found) + *startp = start; + return found; +} + +void * +xa_erase(struct xarray *xa, unsigned long key) +{ + void *datum; + + mutex_enter(&xa->xa_lock); + datum = radix_tree_remove_node(&xa->xa_tree, key); + mutex_exit(&xa->xa_lock); + + return datum; +}