Module Name:    src
Committed By:   martin
Date:           Tue Apr 23 10:16:52 UTC 2019

Modified Files:
        src/sys/external/bsd/common/include/linux [netbsd-8]: err.h errno.h
        src/sys/external/bsd/drm2/dist/drm/nouveau [netbsd-8]: nouveau_drm.c
            nouveau_fence.c
        src/sys/external/bsd/drm2/drm [netbsd-8]: drm_drv.c
        src/sys/external/bsd/drm2/include/drm [netbsd-8]: drm_wait_netbsd.h
        src/sys/external/bsd/drm2/linux [netbsd-8]: linux_ww_mutex.c

Log Message:
Pull up following revision(s) via patch (requested by mrg in ticket #1242):

        sys/external/bsd/common/include/linux/err.h: revision 1.3
        sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h: revision 1.15
        sys/external/bsd/common/include/linux/errno.h: revision 1.4
        sys/external/bsd/drm2/dist/drm/nouveau/nouveau_drm.c: revision 1.17
        sys/external/bsd/drm2/linux/linux_ww_mutex.c: revision 1.6
        sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c: revision 1.14

fix various problems i've seen where cv_*wait*() return ERESTART,
which is -3 in netbsd, which we have mapped linux ERESTARTSYS to.

this has a problem because linux code often returns errors and
pointers in the same value, and pointer values between -4095 and
- -1 are considered as error returns, but -3 ends up as 3 and thus
is not considered an error, and mayhem ensues.

with this in place my kabylake system seems actually stable, i
have not triggered any of my prior issues in almost 4 weeks now.

Taylor asked me to write up a description and then wrote most of
the text below for me :-)

In Linux code, we always work with ERESTARTSYS so the code meaning
start over is a positive NetBSD errno safe for PTR_ERR/ERR_PTR.

To achieve this:

1. adapt all cv_waits that return to Linux so they map ERESTART to
   ERESTARTSYS, and

2. adapt all returns to userland so they convert ERESTARTSYS to
   ERESTART.

Leave EINTR and all other error codes alone.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.1.16.1 src/sys/external/bsd/common/include/linux/err.h
cvs rdiff -u -r1.3 -r1.3.24.1 \
    src/sys/external/bsd/common/include/linux/errno.h
cvs rdiff -u -r1.8 -r1.8.10.1 \
    src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_drm.c
cvs rdiff -u -r1.4.10.1 -r1.4.10.2 \
    src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c
cvs rdiff -u -r1.17.10.1 -r1.17.10.2 src/sys/external/bsd/drm2/drm/drm_drv.c
cvs rdiff -u -r1.14 -r1.14.10.1 \
    src/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h
cvs rdiff -u -r1.2.10.2 -r1.2.10.3 \
    src/sys/external/bsd/drm2/linux/linux_ww_mutex.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/common/include/linux/err.h
diff -u src/sys/external/bsd/common/include/linux/err.h:1.1 src/sys/external/bsd/common/include/linux/err.h:1.1.16.1
--- src/sys/external/bsd/common/include/linux/err.h:1.1	Tue Aug 18 21:10:56 2015
+++ src/sys/external/bsd/common/include/linux/err.h	Tue Apr 23 10:16:51 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: err.h,v 1.1 2015/08/18 21:10:56 skrll Exp $	*/
+/*	$NetBSD: err.h,v 1.1.16.1 2019/04/23 10:16:51 martin Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
 #include <sys/errno.h>
 #include <sys/systm.h>
 
-#define	MAX_ERRNO	ELAST
+#define	MAX_ERRNO	4095
 
 static inline bool
 IS_ERR_VALUE(uintptr_t n)

Index: src/sys/external/bsd/common/include/linux/errno.h
diff -u src/sys/external/bsd/common/include/linux/errno.h:1.3 src/sys/external/bsd/common/include/linux/errno.h:1.3.24.1
--- src/sys/external/bsd/common/include/linux/errno.h:1.3	Wed Jul 16 20:56:24 2014
+++ src/sys/external/bsd/common/include/linux/errno.h	Tue Apr 23 10:16:51 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: errno.h,v 1.3 2014/07/16 20:56:24 riastradh Exp $	*/
+/*	$NetBSD: errno.h,v 1.3.24.1 2019/04/23 10:16:51 martin Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -35,7 +35,10 @@
  * - Linux consistently passes around negative errno values.  NetBSD
  *   consistently passes around positive ones, except the special magic
  *   in-kernel ones (EJUSTRETURN, ERESTART, &c.) which should not be
- *   exposed to userland.  Be careful!
+ *   exposed to userland *or* linux-only code using the negative pointer
+ *   means error return pattern.  Be careful!  If Using ERESTARTSYS from
+ *   Linux code, be sure it is remapped back to ERESTART before NetBSD
+ *   code sees it.
  */
 
 #ifndef _LINUX_ERRNO_H_
@@ -43,7 +46,7 @@
 
 #include <sys/errno.h>
 
-#define	ERESTARTSYS	ERESTART
+#define	ERESTARTSYS	(ELAST+1)	/* XXX */
 #define	ENOTSUPP	ENOTSUP	/* XXX ???  */
 #define	EREMOTEIO	EIO	/* XXX Urk...  */
 #define	ECHRNG		ERANGE	/* XXX ??? */

Index: src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_drm.c
diff -u src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_drm.c:1.8 src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_drm.c:1.8.10.1
--- src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_drm.c:1.8	Thu Feb 11 04:51:44 2016
+++ src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_drm.c	Tue Apr 23 10:16:52 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: nouveau_drm.c,v 1.8 2016/02/11 04:51:44 riastradh Exp $	*/
+/*	$NetBSD: nouveau_drm.c,v 1.8.10.1 2019/04/23 10:16:52 martin Exp $	*/
 
 /*
  * Copyright 2012 Red Hat Inc.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nouveau_drm.c,v 1.8 2016/02/11 04:51:44 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nouveau_drm.c,v 1.8.10.1 2019/04/23 10:16:52 martin Exp $");
 
 #include <linux/console.h>
 #include <linux/module.h>
@@ -759,7 +759,8 @@ nouveau_drm_open(struct drm_device *dev,
 	/* need to bring up power immediately if opening device */
 	ret = pm_runtime_get_sync(dev->dev);
 	if (ret < 0 && ret != -EACCES)
-		return ret;
+		/* XXX errno Linux->NetBSD */
+		return -ret;
 
 #ifndef __NetBSD__
 	get_task_comm(tmpname, current);

Index: src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c
diff -u src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c:1.4.10.1 src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c:1.4.10.2
--- src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c:1.4.10.1	Fri Aug 31 17:35:51 2018
+++ src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c	Tue Apr 23 10:16:52 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: nouveau_fence.c,v 1.4.10.1 2018/08/31 17:35:51 martin Exp $	*/
+/*	$NetBSD: nouveau_fence.c,v 1.4.10.2 2019/04/23 10:16:52 martin Exp $	*/
 
 /*
  * Copyright (C) 2007 Ben Skeggs.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nouveau_fence.c,v 1.4.10.1 2018/08/31 17:35:51 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nouveau_fence.c,v 1.4.10.2 2019/04/23 10:16:52 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/xcall.h>
@@ -567,6 +567,8 @@ nouveau_fence_wait(struct nouveau_fence 
 		if (lazy && delay_usec >= 1000*hztoms(1)) {
 			/* XXX errno NetBSD->Linux */
 			ret = -kpause("nvfencew", intr, 1, NULL);
+			if (ret == -ERESTART)
+				ret = -ERESTARTSYS;
 			if (ret != -EWOULDBLOCK)
 				break;
 		} else {

Index: src/sys/external/bsd/drm2/drm/drm_drv.c
diff -u src/sys/external/bsd/drm2/drm/drm_drv.c:1.17.10.1 src/sys/external/bsd/drm2/drm/drm_drv.c:1.17.10.2
--- src/sys/external/bsd/drm2/drm/drm_drv.c:1.17.10.1	Fri Dec  8 05:43:51 2017
+++ src/sys/external/bsd/drm2/drm/drm_drv.c	Tue Apr 23 10:16:52 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_drv.c,v 1.17.10.1 2017/12/08 05:43:51 msaitoh Exp $	*/
+/*	$NetBSD: drm_drv.c,v 1.17.10.2 2019/04/23 10:16:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.17.10.1 2017/12/08 05:43:51 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.17.10.2 2019/04/23 10:16:52 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -326,6 +326,8 @@ fail2:	spin_lock(&dev->count_lock);
 		(void)drm_lastclose(dev);
 fail1:	drm_minor_release(dminor);
 fail0:	KASSERT(error);
+	if (error == ERESTARTSYS)
+		error = ERESTART;
 	return error;
 }
 
@@ -445,6 +447,8 @@ drm_read(struct file *fp, off_t *off, st
 	}
 
 	/* Success!  */
+	if (error == ERESTARTSYS)
+		error = ERESTART;
 	return error;
 }
 
@@ -678,6 +682,8 @@ drm_ioctl(struct file *fp, unsigned long
 	if (!ISSET(ioctl->flags, DRM_UNLOCKED))
 		mutex_unlock(&drm_global_mutex);
 
+	if (error == ERESTARTSYS)
+		error = ERESTART;
 	return error;
 }
 
@@ -690,11 +696,14 @@ drm_fop_mmap(struct file *fp, off_t *off
 	int error;
 
 	KASSERT(fp == file->filp);
-	error = (*dev->driver->mmap_object)(dev, *offp, len, prot, uobjp,
+	/* XXX errno Linux->NetBSD */
+	error = -(*dev->driver->mmap_object)(dev, *offp, len, prot, uobjp,
 	    offp, file->filp);
 	*maxprotp = prot;
 	*advicep = UVM_ADV_RANDOM;
-	return -error;
+	if (error == ERESTARTSYS)
+		error = ERESTART;
+	return error;
 }
 
 static int

Index: src/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h
diff -u src/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h:1.14 src/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h:1.14.10.1
--- src/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h:1.14	Fri May 13 15:25:57 2016
+++ src/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h	Tue Apr 23 10:16:52 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_wait_netbsd.h,v 1.14 2016/05/13 15:25:57 christos Exp $	*/
+/*	$NetBSD: drm_wait_netbsd.h,v 1.14.10.1 2019/04/23 10:16:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -39,6 +39,7 @@
 #include <sys/mutex.h>
 #include <sys/systm.h>
 
+#include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 
@@ -114,10 +115,13 @@ DRM_SPIN_WAKEUP_ALL(drm_waitqueue_t *q, 
  * Like the legacy DRM_WAIT_ON, DRM_SPIN_WAIT_ON returns
  *
  * . -EBUSY if timed out (yes, -EBUSY, not -ETIMEDOUT or -EWOULDBLOCK),
- * . -EINTR/-ERESTART if interrupted by a signal, or
+ * . -EINTR/-ERESTARTSYS if interrupted by a signal, or
  * . 0 if the condition was true before or just after the timeout.
  *
  * Note that cv_timedwait* return -EWOULDBLOCK, not -EBUSY, on timeout.
+ *
+ * Note that ERESTARTSYS is actually ELAST+1 and only used in Linux
+ * code and must be converted for use in NetBSD code (user or kernel.)
  */
 
 #define	DRM_SPIN_WAIT_ON(RET, Q, INTERLOCK, TICKS, CONDITION)	do	      \
@@ -148,6 +152,8 @@ DRM_SPIN_WAKEUP_ALL(drm_waitqueue_t *q, 
 		else							      \
 			_dswo_ticks = 0;				      \
 		if (RET) {						      \
+			if ((RET) == -ERESTART)				      \
+				(RET) = -ERESTARTSYS;			      \
 			if ((RET) == -EWOULDBLOCK)			      \
 				/* Waited only one tick.  */		      \
 				continue;				      \
@@ -165,26 +171,29 @@ DRM_SPIN_WAKEUP_ALL(drm_waitqueue_t *q, 
  *
  * The untimed DRM_*WAIT*_UNTIL macros return
  *
- * . -EINTR/-ERESTART if interrupted by a signal, or
+ * . -EINTR/-ERESTARTSYS if interrupted by a signal, or
  * . zero if the condition evaluated
  *
  * The timed DRM_*TIMED_WAIT*_UNTIL macros return
  *
- * . -EINTR/-ERESTART if interrupted by a signal,
+ * . -EINTR/-ERESTARTSYS if interrupted by a signal,
  * . 0 if the condition was false after the timeout,
  * . 1 if the condition was true just after the timeout, or
  * . the number of ticks remaining if the condition was true before the
  * timeout.
  *
- * Contrast DRM_SPIN_WAIT_ON which returns -EINTR/-ERESTART on signal,
+ * Contrast DRM_SPIN_WAIT_ON which returns -EINTR/-ERESTARTSYS on signal,
  * -EBUSY on timeout, and zero on success; and cv_*wait*, which return
- * -EINTR/-ERESTART on signal, -EWOULDBLOCK on timeout, and zero on
+ * -EINTR/-ERESTARTSYS on signal, -EWOULDBLOCK on timeout, and zero on
  * success.
  *
  * XXX In retrospect, giving the timed and untimed macros a different
  * return convention from one another to match Linux may have been a
  * bad idea.  All of this inconsistent timeout return convention logic
  * has been a consistent source of bugs.
+ *
+ * Note that ERESTARTSYS is actually ELAST+1 and only used in Linux
+ * code and must be converted for use in NetBSD code (user or kernel.)
  */
 
 #define	_DRM_WAIT_UNTIL(RET, WAIT, Q, INTERLOCK, CONDITION) do		\
@@ -199,8 +208,11 @@ DRM_SPIN_WAKEUP_ALL(drm_waitqueue_t *q, 
 		}							\
 		/* XXX errno NetBSD->Linux */				\
 		(RET) = -WAIT((Q), &(INTERLOCK)->mtx_lock);		\
-		if (RET)						\
+		if (RET) {						\
+			if ((RET) == -ERESTART)				\
+				(RET) = -ERESTARTSYS;			\
 			break;						\
+		}							\
 	}								\
 } while (0)
 
@@ -240,6 +252,8 @@ DRM_SPIN_WAKEUP_ALL(drm_waitqueue_t *q, 
 		else							\
 			_dtwu_ticks = 0;				\
 		if (RET) {						\
+			if ((RET) == -ERESTART)				\
+				(RET) = -ERESTARTSYS;			\
 			if ((RET) == -EWOULDBLOCK)			\
 				(RET) = (CONDITION) ? 1 : 0;		\
 			break;						\
@@ -270,6 +284,8 @@ DRM_SPIN_WAKEUP_ALL(drm_waitqueue_t *q, 
 	while (!(CONDITION)) {						\
 		/* XXX errno NetBSD->Linux */				\
 		(RET) = -WAIT((Q), &(INTERLOCK)->sl_lock);		\
+		if ((RET) == -ERESTART)					\
+			(RET) = -ERESTARTSYS;				\
 		if (RET)						\
 			break;						\
 	}								\
@@ -311,6 +327,8 @@ DRM_SPIN_WAKEUP_ALL(drm_waitqueue_t *q, 
 		else							\
 			_dstwu_ticks = 0;				\
 		if (RET) {						\
+			if ((RET) == -ERESTART)				\
+				(RET) = -ERESTARTSYS;			\
 			if ((RET) == -EWOULDBLOCK)			\
 				(RET) = (CONDITION) ? 1 : 0;		\
 			break;						\

Index: src/sys/external/bsd/drm2/linux/linux_ww_mutex.c
diff -u src/sys/external/bsd/drm2/linux/linux_ww_mutex.c:1.2.10.2 src/sys/external/bsd/drm2/linux/linux_ww_mutex.c:1.2.10.3
--- src/sys/external/bsd/drm2/linux/linux_ww_mutex.c:1.2.10.2	Thu Sep 27 14:38:56 2018
+++ src/sys/external/bsd/drm2/linux/linux_ww_mutex.c	Tue Apr 23 10:16:52 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_ww_mutex.c,v 1.2.10.2 2018/09/27 14:38:56 martin Exp $	*/
+/*	$NetBSD: linux_ww_mutex.c,v 1.2.10.3 2019/04/23 10:16:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_ww_mutex.c,v 1.2.10.2 2018/09/27 14:38:56 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_ww_mutex.c,v 1.2.10.3 2019/04/23 10:16:52 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
@@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_ww_mut
 #include <sys/rbtree.h>
 
 #include <linux/ww_mutex.h>
+#include <linux/errno.h>
 
 #define	WW_WANTLOCK(WW)							      \
 	LOCKDEBUG_WANTLOCK((WW)->wwm_debug, (WW),			      \
@@ -250,6 +251,8 @@ ww_mutex_state_wait_sig(struct ww_mutex 
 	do {
 		/* XXX errno NetBSD->Linux */
 		ret = -cv_wait_sig(&mutex->wwm_cv, &mutex->wwm_lock);
+		if (ret == -ERESTART)
+			ret = -ERESTARTSYS;
 		if (ret)
 			break;
 	} while (mutex->wwm_state == state);
@@ -315,6 +318,8 @@ ww_mutex_lock_wait_sig(struct ww_mutex *
 	do {
 		/* XXX errno NetBSD->Linux */
 		ret = -cv_wait_sig(&mutex->wwm_cv, &mutex->wwm_lock);
+		if (ret == -ERESTART)
+			ret = -ERESTARTSYS;
 		if (ret)
 			goto out;
 	} while (!(((mutex->wwm_state == WW_CTX) ||

Reply via email to