Module Name:    src
Committed By:   riastradh
Date:           Mon Aug 27 15:08:54 UTC 2018

Modified Files:
        src/sys/external/bsd/drm2/include/linux: atomic.h
        src/sys/external/bsd/drm2/linux: files.drmkms_linux linux_module.c
Added Files:
        src/sys/external/bsd/drm2/linux: linux_atomic64.c

Log Message:
Hash-locked atomic64 to give ports like powerpc32 a chance at radeon.


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/external/bsd/drm2/include/linux/atomic.h
cvs rdiff -u -r1.15 -r1.16 src/sys/external/bsd/drm2/linux/files.drmkms_linux
cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/linux/linux_atomic64.c
cvs rdiff -u -r1.8 -r1.9 src/sys/external/bsd/drm2/linux/linux_module.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/atomic.h
diff -u src/sys/external/bsd/drm2/include/linux/atomic.h:1.14 src/sys/external/bsd/drm2/include/linux/atomic.h:1.15
--- src/sys/external/bsd/drm2/include/linux/atomic.h:1.14	Mon Aug 27 13:58:16 2018
+++ src/sys/external/bsd/drm2/include/linux/atomic.h	Mon Aug 27 15:08:54 2018
@@ -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
 	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;
 };

Index: src/sys/external/bsd/drm2/linux/files.drmkms_linux
diff -u src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.15 src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.16
--- src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.15	Mon Aug 27 14:16:38 2018
+++ src/sys/external/bsd/drm2/linux/files.drmkms_linux	Mon Aug 27 15:08:54 2018
@@ -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

Index: src/sys/external/bsd/drm2/linux/linux_module.c
diff -u src/sys/external/bsd/drm2/linux/linux_module.c:1.8 src/sys/external/bsd/drm2/linux/linux_module.c:1.9
--- src/sys/external/bsd/drm2/linux/linux_module.c:1.8	Mon Aug 27 13:33:59 2018
+++ src/sys/external/bsd/drm2/linux/linux_module.c	Mon Aug 27 15:08:54 2018
@@ -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();

Added files:

Index: src/sys/external/bsd/drm2/linux/linux_atomic64.c
diff -u /dev/null src/sys/external/bsd/drm2/linux/linux_atomic64.c:1.1
--- /dev/null	Mon Aug 27 15:08:54 2018
+++ src/sys/external/bsd/drm2/linux/linux_atomic64.c	Mon Aug 27 15:08:54 2018
@@ -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

Reply via email to