diff options
| author | riastradh <riastradh@NetBSD.org> | 2021-12-19 11:51:07 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2021-12-19 11:51:07 +0000 |
| commit | bbdbe46ed83b6d8f8135684ff4be338b246fca73 (patch) | |
| tree | 8b42dce096e447379b737bc34e4ddf3ebe870a01 /sys/external | |
| parent | 0643055931e04a6eb351ab466dd5a6727222edef (diff) | |
linux: Draft half-arsed xarray shims
Diffstat (limited to 'sys/external')
| -rw-r--r-- | sys/external/bsd/drm2/include/linux/xarray.h | 26 | ||||
| -rw-r--r-- | sys/external/bsd/drm2/linux/files.drmkms_linux | 3 | ||||
| -rw-r--r-- | sys/external/bsd/drm2/linux/linux_xa.c | 181 |
3 files changed, 202 insertions, 8 deletions
diff --git a/sys/external/bsd/drm2/include/linux/xarray.h b/sys/external/bsd/drm2/include/linux/xarray.h index e9268b23882..c3c7da29480 100644 --- a/sys/external/bsd/drm2/include/linux/xarray.h +++ b/sys/external/bsd/drm2/include/linux/xarray.h @@ -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 diff --git a/sys/external/bsd/drm2/linux/files.drmkms_linux b/sys/external/bsd/drm2/linux/files.drmkms_linux index 2c969c2a0c9..f2948c367d4 100644 --- a/sys/external/bsd/drm2/linux/files.drmkms_linux +++ b/sys/external/bsd/drm2/linux/files.drmkms_linux @@ -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.c drmkms_linux 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 diff --git a/sys/external/bsd/drm2/linux/linux_xa.c b/sys/external/bsd/drm2/linux/linux_xa.c new file mode 100644 index 00000000000..0701b70b6e4 --- /dev/null +++ b/sys/external/bsd/drm2/linux/linux_xa.c @@ -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; +} |
