Module Name: src Committed By: riastradh Date: Sun Dec 19 01:22:15 UTC 2021
Modified Files: src/sys/external/bsd/drm2/linux: files.drmkms_linux linux_module.c Added Files: src/sys/external/bsd/drm2/include/linux: wait_bit.h src/sys/external/bsd/drm2/linux: linux_wait_bit.c Log Message: linux/wait_bit.h To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/include/linux/wait_bit.h cvs rdiff -u -r1.19 -r1.20 src/sys/external/bsd/drm2/linux/files.drmkms_linux cvs rdiff -u -r1.10 -r1.11 src/sys/external/bsd/drm2/linux/linux_module.c cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/linux/linux_wait_bit.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/linux/files.drmkms_linux diff -u src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.19 src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.20 --- src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.19 Sun Dec 19 00:58:22 2021 +++ src/sys/external/bsd/drm2/linux/files.drmkms_linux Sun Dec 19 01:22:15 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.drmkms_linux,v 1.19 2021/12/19 00:58:22 riastradh Exp $ +# $NetBSD: files.drmkms_linux,v 1.20 2021/12/19 01:22:15 riastradh Exp $ define drmkms_linux: i2cexec, i2c_bitbang @@ -18,5 +18,6 @@ file external/bsd/drm2/linux/linux_pci.c file external/bsd/drm2/linux/linux_rcu.c drmkms_linux file external/bsd/drm2/linux/linux_reservation.c drmkms_linux file external/bsd/drm2/linux/linux_srcu.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 Index: src/sys/external/bsd/drm2/linux/linux_module.c diff -u src/sys/external/bsd/drm2/linux/linux_module.c:1.10 src/sys/external/bsd/drm2/linux/linux_module.c:1.11 --- src/sys/external/bsd/drm2/linux/linux_module.c:1.10 Sun Dec 19 01:17:14 2021 +++ src/sys/external/bsd/drm2/linux/linux_module.c Sun Dec 19 01:22:15 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_module.c,v 1.10 2021/12/19 01:17:14 riastradh Exp $ */ +/* $NetBSD: linux_module.c,v 1.11 2021/12/19 01:22:15 riastradh Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_module.c,v 1.10 2021/12/19 01:17:14 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_module.c,v 1.11 2021/12/19 01:22:15 riastradh Exp $"); #include <sys/module.h> #ifndef _MODULE @@ -44,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_module #include <linux/mutex.h> #include <linux/rcupdate.h> #include <linux/tasklet.h> +#include <linux/wait_bit.h> #include <linux/workqueue.h> MODULE(MODULE_CLASS_MISC, drmkms_linux, "i2cexec"); @@ -96,10 +97,17 @@ linux_init(void) goto fail6; } + error = linux_wait_bit_init(); + if (error) { + printf("linux: unable to initialize wait_bit: %d\n", error); + goto fail7; + } + return 0; -fail7: __unused - linux_tasklets_fini(); +fail8: __unused + linux_wait_bit_fini(); +fail7: linux_tasklets_fini(); fail6: linux_atomic64_fini(); fail5: linux_writecomb_fini(); fail4: linux_workqueue_fini(); @@ -126,6 +134,7 @@ static void linux_fini(void) { + linux_wait_bit_fini(); linux_tasklets_fini(); linux_atomic64_fini(); linux_writecomb_fini(); Added files: Index: src/sys/external/bsd/drm2/include/linux/wait_bit.h diff -u /dev/null src/sys/external/bsd/drm2/include/linux/wait_bit.h:1.1 --- /dev/null Sun Dec 19 01:22:15 2021 +++ src/sys/external/bsd/drm2/include/linux/wait_bit.h Sun Dec 19 01:22:15 2021 @@ -0,0 +1,45 @@ +/* $NetBSD: wait_bit.h,v 1.1 2021/12/19 01:22:15 riastradh Exp $ */ + +/*- + * Copyright (c) 2018 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * 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. + */ + +#ifndef _LINUX_WAIT_BIT_H_ +#define _LINUX_WAIT_BIT_H_ + +#define wait_on_bit_timeout linux_wait_on_bit_timeout +#define wake_up_bit linux_wake_up_bit + +int linux_wait_bit_init(void); +void linux_wait_bit_fini(void); + +void wake_up_bit(const volatile unsigned long *, unsigned); +int wait_on_bit_timeout(const volatile unsigned long *, unsigned, int, + unsigned long); + +#endif /* _LINUX_WAIT_BIT_H_ */ Index: src/sys/external/bsd/drm2/linux/linux_wait_bit.c diff -u /dev/null src/sys/external/bsd/drm2/linux/linux_wait_bit.c:1.1 --- /dev/null Sun Dec 19 01:22:15 2021 +++ src/sys/external/bsd/drm2/linux/linux_wait_bit.c Sun Dec 19 01:22:15 2021 @@ -0,0 +1,162 @@ +/* $NetBSD: linux_wait_bit.c,v 1.1 2021/12/19 01:22:15 riastradh Exp $ */ + +/*- + * Copyright (c) 2018 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * 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_wait_bit.c,v 1.1 2021/12/19 01:22:15 riastradh Exp $"); + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/bitops.h> +#include <sys/condvar.h> +#include <sys/mutex.h> +#include <sys/systm.h> + +#include <linux/bitops.h> +#include <linux/sched.h> +#include <linux/wait_bit.h> + +static struct { + struct waitbitentry { + kmutex_t lock; + kcondvar_t cv; + } ent; + char pad[CACHE_LINE_SIZE - sizeof(struct waitbitentry)]; +} waitbittab[PAGE_SIZE/CACHE_LINE_SIZE] __cacheline_aligned; +CTASSERT(sizeof(waitbittab) == PAGE_SIZE); +CTASSERT(sizeof(waitbittab[0]) == CACHE_LINE_SIZE); + +int +linux_wait_bit_init(void) +{ + size_t i; + + for (i = 0; i < __arraycount(waitbittab); i++) { + mutex_init(&waitbittab[i].ent.lock, MUTEX_DEFAULT, IPL_VM); + cv_init(&waitbittab[i].ent.cv, "waitbit"); + } + + return 0; +} + +void +linux_wait_bit_fini(void) +{ + size_t i; + + for (i = 0; i < __arraycount(waitbittab); i++) { + cv_destroy(&waitbittab[i].ent.cv); + mutex_destroy(&waitbittab[i].ent.lock); + } +} + +static inline size_t +wait_bit_hash(const volatile unsigned long *bitmap, unsigned bit) +{ + /* Try to avoid cache line collisions. */ + const volatile unsigned long *word = bitmap + bit/(NBBY*sizeof(*word)); + + return ((uintptr_t)word >> ilog2(CACHE_LINE_SIZE)) % + __arraycount(waitbittab); +} + +static struct waitbitentry * +wait_bit_enter(const volatile unsigned long *bitmap, unsigned bit) +{ + struct waitbitentry *wbe = &waitbittab[wait_bit_hash(bitmap, bit)].ent; + + mutex_enter(&wbe->lock); + + return wbe; +} + +static void +wait_bit_exit(struct waitbitentry *wbe) +{ + + mutex_exit(&wbe->lock); +} + +void +wake_up_bit(const volatile unsigned long *bitmap, unsigned bit) +{ + struct waitbitentry *wbe; + + wbe = wait_bit_enter(bitmap, bit); + cv_broadcast(&wbe->cv); + wait_bit_exit(wbe); +} + +int +wait_on_bit_timeout(const volatile unsigned long *bitmap, unsigned bit, + int flags, unsigned long timeout) +{ + struct waitbitentry *wbe; + int error, ret; + + if (test_bit(bit, bitmap)) + return timeout; + + wbe = wait_bit_enter(bitmap, bit); + + while (!test_bit(bit, bitmap)) { + unsigned starttime, endtime; + + starttime = hardclock_ticks; + if (flags & TASK_UNINTERRUPTIBLE) { + error = cv_timedwait(&wbe->cv, &wbe->lock, + MIN(INT_MAX, timeout)); + } else { + error = cv_timedwait_sig(&wbe->cv, &wbe->lock, + MIN(INT_MAX, timeout)); + } + endtime = hardclock_ticks; + + /* If we timed out, return zero time left. */ + if (error == EWOULDBLOCK || endtime - starttime < timeout) { + ret = 0; + goto out; + } + + /* If we were interrupted, return -ERESTARTSYS. */ + if (error == EINTR || error == EWOULDBLOCK) { + ret = -ERESTARTSYS; + goto out; + } + + /* Otherwise, debit the time spent. */ + timeout -= (endtime - starttime); + } + /* Bit is set. Return the time left. */ + ret = timeout; + +out: wait_bit_exit(wbe); + return ret; +}