diff options
| author | riastradh <riastradh@NetBSD.org> | 2018-08-27 15:08:54 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2018-08-27 15:08:54 +0000 |
| commit | 09bed39b6051cb8416edc018bfe7fa41281faeef (patch) | |
| tree | 8a3b1ec3d2fae574e05f2a8d7212fc1026cc68c0 /sys | |
| parent | 8d560b6cdce110d89295816812954f9534523fcf (diff) | |
Hash-locked atomic64 to give ports like powerpc32 a chance at radeon.
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/external/bsd/drm2/include/linux/atomic.h | 25 | ||||
| -rw-r--r-- | sys/external/bsd/drm2/linux/files.drmkms_linux | 3 | ||||
| -rw-r--r-- | sys/external/bsd/drm2/linux/linux_atomic64.c | 194 | ||||
| -rw-r--r-- | sys/external/bsd/drm2/linux/linux_module.c | 17 |
4 files changed, 233 insertions, 6 deletions
diff --git a/sys/external/bsd/drm2/include/linux/atomic.h b/sys/external/bsd/drm2/include/linux/atomic.h index 7433d34313a..703c130ba1d 100644 --- a/sys/external/bsd/drm2/include/linux/atomic.h +++ b/sys/external/bsd/drm2/include/linux/atomic.h @@ -1,4 +1,4 @@ -/* $NetBSD: atomic.h,v 1.14 2018/08/27 13:58:16 riastradh Exp $ */ +/* $NetBSD: atomic.h,v 1.15 2018/08/27 15:08:54 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -229,6 +229,11 @@ struct atomic64 { typedef struct atomic64 atomic64_t; +int linux_atomic64_init(void); +void linux_atomic64_fini(void); + +#ifdef __HAVE_ATOMIC64_OPS + static inline uint64_t atomic64_read(const struct atomic64 *a) { @@ -286,6 +291,24 @@ atomic64_cmpxchg(struct atomic64 *atomic, uint64_t expect, uint64_t new) return old; } +#else /* !defined(__HAVE_ATOMIC64_OPS) */ + +#define atomic64_read linux_atomic64_read +#define atomic64_set linux_atomic64_set +#define atomic64_add linux_atomic64_add +#define atomic64_sub linux_atomic64_sub +#define atomic64_xchg linux_atomic64_xchg +#define atomic64_cmpxchg linux_atomic64_cmpxchg + +uint64_t atomic64_read(const struct atomic64 *); +void atomic64_set(struct atomic64 *, uint64_t); +void atomic64_add(long long, struct atomic64 *); +void atomic64_sub(long long, struct atomic64 *); +uint64_t atomic64_xchg(struct atomic64 *, uint64_t); +uint64_t atomic64_cmpxchg(struct atomic64 *, uint64_t, uint64_t); + +#endif + struct atomic_long { volatile unsigned long al_v; }; diff --git a/sys/external/bsd/drm2/linux/files.drmkms_linux b/sys/external/bsd/drm2/linux/files.drmkms_linux index 7d4efc30035..6a945c227bf 100644 --- a/sys/external/bsd/drm2/linux/files.drmkms_linux +++ b/sys/external/bsd/drm2/linux/files.drmkms_linux @@ -1,10 +1,11 @@ -# $NetBSD: files.drmkms_linux,v 1.15 2018/08/27 14:16:38 riastradh Exp $ +# $NetBSD: files.drmkms_linux,v 1.16 2018/08/27 15:08:54 riastradh Exp $ define drmkms_linux: i2cexec, i2c_bitbang makeoptions drmkms_linux CPPFLAGS+="-I$S/external/bsd/common/include" makeoptions drmkms_linux CPPFLAGS+="-I$S/external/bsd/drm2/include" +file external/bsd/drm2/linux/linux_atomic64.c drmkms_linux file external/bsd/drm2/linux/linux_dmi.c drmkms_linux file external/bsd/drm2/linux/linux_fence.c drmkms_linux file external/bsd/drm2/linux/linux_i2c.c drmkms_linux diff --git a/sys/external/bsd/drm2/linux/linux_atomic64.c b/sys/external/bsd/drm2/linux/linux_atomic64.c new file mode 100644 index 00000000000..41e338bef32 --- /dev/null +++ b/sys/external/bsd/drm2/linux/linux_atomic64.c @@ -0,0 +1,194 @@ +/* $NetBSD: linux_atomic64.c,v 1.1 2018/08/27 15:08:54 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_atomic64.c,v 1.1 2018/08/27 15:08:54 riastradh Exp $"); + +#include <sys/param.h> +#include <sys/bitops.h> +#include <sys/lock.h> + +#include <linux/atomic.h> + +#ifdef __HAVE_ATOMIC64_OPS + +int +linux_atomic64_init(void) +{ + return 0; +} + +void +linux_atomic64_fini(void) +{ +} + +#else + +static struct { + kmutex_t lock; + uint32_t gen; /* for unlocked read */ + char pad[CACHE_LINE_SIZE - + sizeof(kmutex_t) - sizeof(uint32_t)]; +} atomic64_tab[PAGE_SIZE/CACHE_LINE_SIZE] __cacheline_aligned; +CTASSERT(sizeof(atomic64_tab) == PAGE_SIZE); +CTASSERT(sizeof(atomic64_tab[0]) == CACHE_LINE_SIZE); + +int +linux_atomic64_init(void) +{ + size_t i; + + for (i = 0; i < __arraycount(atomic64_tab); i++) { + mutex_init(&atomic64_tab[i].lock, MUTEX_DEFAULT, IPL_HIGH); + atomic64_tab[i].gen = 0; + } + + return 0; +} + +void +linux_atomic64_fini(void) +{ + size_t i; + + for (i = 0; i < __arraycount(atomic64_tab); i++) { + KASSERT((atomic64_tab[i].gen & 1) == 0); + mutex_destroy(&atomic64_tab[i].lock); + } +} + +static inline size_t +atomic64_hash(const struct atomic64 *a) +{ + + return ((uintptr_t)a >> ilog2(CACHE_LINE_SIZE)) % + __arraycount(atomic64_tab); +} + +static void +atomic64_lock(struct atomic64 *a) +{ + size_t i = atomic64_hash(a); + + mutex_spin_enter(&atomic64_tab[i].lock); + KASSERT((atomic64_tab[i].gen & 1) == 0); + atomic64_tab[i].gen |= 1; + membar_producer(); +} + +static void +atomic64_unlock(struct atomic64 *a) +{ + size_t i = atomic64_hash(a); + + KASSERT(mutex_owned(&atomic64_tab[i].lock)); + KASSERT((atomic64_tab[i].gen & 1) == 1); + + membar_producer(); + atomic64_tab[i].gen |= 1; /* paranoia */ + atomic64_tab[i].gen++; + mutex_spin_exit(&atomic64_tab[i].lock); +} + +uint64_t +atomic64_read(const struct atomic64 *a) +{ + size_t i = atomic64_hash(a); + uint32_t gen; + uint64_t value; + + do { + while (__predict_false((gen = atomic64_tab[i].gen) & 1)) + SPINLOCK_BACKOFF_HOOK; + membar_consumer(); + value = a->a_v; + membar_consumer(); + } while (__predict_false(atomic64_tab[i].gen != gen)); + + return value; +} + +void +atomic64_set(struct atomic64 *a, uint64_t value) +{ + + atomic64_lock(a); + a->a_v = value; + atomic64_unlock(a); +} + +void +atomic64_add(long long delta, struct atomic64 *a) +{ + + atomic64_lock(a); + a->a_v += delta; + atomic64_unlock(a); +} + +void +atomic64_sub(long long delta, struct atomic64 *a) +{ + + atomic64_lock(a); + a->a_v -= delta; + atomic64_unlock(a); +} + +uint64_t +atomic64_xchg(struct atomic64 *a, uint64_t new) +{ + uint64_t old; + + atomic64_lock(a); + old = a->a_v; + a->a_v = new; + atomic64_unlock(a); + + return old; +} + +uint64_t +atomic64_cmpxchg(struct atomic64 *a, uint64_t expect, uint64_t new) +{ + uint64_t old; + + atomic64_lock(a); + old = a->a_v; + if (old == expect) + a->a_v = new; + atomic64_unlock(a); + + return old; +} + +#endif diff --git a/sys/external/bsd/drm2/linux/linux_module.c b/sys/external/bsd/drm2/linux/linux_module.c index 398f6f28c83..c2652f08c15 100644 --- a/sys/external/bsd/drm2/linux/linux_module.c +++ b/sys/external/bsd/drm2/linux/linux_module.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_module.c,v 1.8 2018/08/27 13:33:59 riastradh Exp $ */ +/* $NetBSD: linux_module.c,v 1.9 2018/08/27 15:08:54 riastradh Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -30,13 +30,14 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_module.c,v 1.8 2018/08/27 13:33:59 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_module.c,v 1.9 2018/08/27 15:08:54 riastradh Exp $"); #include <sys/module.h> #ifndef _MODULE #include <sys/once.h> #endif +#include <linux/atomic.h> #include <linux/highmem.h> #include <linux/idr.h> #include <linux/io.h> @@ -82,10 +83,17 @@ linux_init(void) goto fail4; } + error = linux_atomic64_init(); + if (error) { + printf("linux: unable to initialize atomic64: %d\n", error); + goto fail5; + } + return 0; -fail5: __unused - linux_writecomb_fini(); +fail6: __unused + linux_atomic64_fini(); +fail5: linux_writecomb_fini(); fail4: linux_workqueue_fini(); fail3: linux_rcu_gc_fini(); fail2: linux_kmap_fini(); @@ -110,6 +118,7 @@ static void linux_fini(void) { + linux_atomic64_fini(); linux_writecomb_fini(); linux_workqueue_fini(); linux_rcu_gc_fini(); |
