git: 51f481235c29 - main - pbio: Add locking and remove D_NEEDGIANT.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 05 May 2022 23:42:31 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=51f481235c29fb38b92fb08a830385e39df80093

commit 51f481235c29fb38b92fb08a830385e39df80093
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-05-05 23:40:04 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2022-05-05 23:40:04 +0000

    pbio: Add locking and remove D_NEEDGIANT.
    
    Use a sx lock to permit uiomove directly into/out of the the per-port
    buffers.  In addition, the sx lock provides a stronger guarantee that
    I think this driver wants which is to single-thread read and write
    calls even while paused.  Finally, replace tsleep with dummy wait
    channels with calls to pause_sig to more clearly communicate the
    intent.
    
    Differential Revision:  https://reviews.freebsd.org/D35081
---
 sys/dev/pbio/pbio.c | 54 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 31 insertions(+), 23 deletions(-)

diff --git a/sys/dev/pbio/pbio.c b/sys/dev/pbio/pbio.c
index 516ec3a73408..0fd841cd5720 100644
--- a/sys/dev/pbio/pbio.c
+++ b/sys/dev/pbio/pbio.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/pbio/pbioio.h>		/* pbio IOCTL definitions */
 #include <sys/uio.h>
 #include <sys/fcntl.h>
+#include <sys/sx.h>
 #include <isa/isavar.h>
 
 /* Function prototypes (these should all be static) */
@@ -84,11 +85,8 @@ static char *port_names[] = {"a", "b", "ch", "cl"};
 
 #define	pbio_addr(dev)		((dev)->si_drv1)
 
-#define	PBIOPRI	((PZERO + 5) | PCATCH)
-
 static struct cdevsw pbio_cdevsw = {
 	.d_version = D_VERSION,
-	.d_flags = D_NEEDGIANT,
 	.d_open = pbioopen,
 	.d_read = pbioread,
 	.d_write = pbiowrite,
@@ -117,6 +115,7 @@ struct pbio_softc {
 	int	iomode;			/* Virtualized I/O mode port value */
 					/* The real port is write-only */
 	struct resource *res;
+	struct sx lock;
 };
 
 typedef	struct pbio_softc *sc_p;
@@ -230,6 +229,7 @@ pbioattach (device_t dev)
 	 */
 	sc->iomode = 0x9b;		/* All ports to input */
 
+	sx_init(&sc->lock, "pbio");
 	for (i = 0; i < PBIO_NPORTS; i++) {
 		make_dev_args_init(&args);
 		args.mda_devsw = &pbio_cdevsw;
@@ -249,10 +249,12 @@ pbioioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag,
     struct thread *td)
 {
 	struct pbio_softc *scp;
-	int port;
+	int error, port;
 
+	error = 0;
 	port = PORT(dev);
 	scp = pbio_addr(dev);
+	sx_xlock(&scp->lock);
 	switch (cmd) {
 	case PBIO_SETDIFF:
 		scp->pd[port].diff = *(int *)data;
@@ -273,16 +275,17 @@ pbioioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag,
 		*(int *)data = scp->pd[port].opace;
 		break;
 	default:
-		return ENXIO;
+		error = ENXIO;
 	}
-	return (0);
+	sx_xunlock(&scp->lock);
+	return (error);
 }
 
 static  int
 pbioopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
 {
 	struct pbio_softc *scp;
-	int ocfg, port;
+	int error, ocfg, port;
 	int portbit;			/* Port configuration bit */
 
 	port = PORT(dev);
@@ -297,6 +300,8 @@ pbioopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
 	}
 	ocfg = scp->iomode;
 
+	error = 0;
+	sx_xlock(&scp->lock);
 	if (oflags & FWRITE)
 		/* Writing == output; zero the bit */
 		pboutb(scp, PBIO_CFG, scp->iomode = (ocfg & (~portbit)));
@@ -304,9 +309,10 @@ pbioopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
 		/* Reading == input; set the bit */
 		pboutb(scp, PBIO_CFG, scp->iomode = (ocfg | portbit));
 	else
-		return (EACCES);
+		error = EACCES;
+	sx_xunlock(&scp->lock);
 
-	return (0);
+	return (error);
 }
 
 /*
@@ -341,8 +347,7 @@ portval(int port, struct pbio_softc *scp, char *val)
 				scp->pd[port].oldval = *val;
 				return (0);
 			}
-			err = tsleep((caddr_t)&(scp->pd[port].diff), PBIOPRI,
-				     "pbiopl", max(1, scp->pd[port].ipace));
+			err = pause_sig("pbiopl", max(1, scp->pd[port].ipace));
 			if (err == EINTR)
 				return (EINTR);
 		} else
@@ -354,26 +359,28 @@ static  int
 pbioread(struct cdev *dev, struct uio *uio, int ioflag)
 {
 	struct pbio_softc *scp;
-	int err, i, port, ret, toread;
+	int err, i, port, toread;
 	char val;
 
 	port = PORT(dev);
 	scp = pbio_addr(dev);
 
+	err = 0;
+	sx_xlock(&scp->lock);
 	while (uio->uio_resid > 0) {
 		toread = min(uio->uio_resid, PBIO_BUFSIZ);
-		if ((ret = uiomove(scp->pd[port].buff, toread, uio)) != 0)
-			return (ret);
+		if ((err = uiomove(scp->pd[port].buff, toread, uio)) != 0)
+			break;
 		for (i = 0; i < toread; i++) {
 			if ((err = portval(port, scp, &val)) != 0)
-				return (err);
+				break;
 			scp->pd[port].buff[i] = val;
 			if (!scp->pd[port].diff && scp->pd[port].ipace)
-				tsleep((caddr_t)&(scp->pd[port].ipace), PBIOPRI,
-					"pbioip", scp->pd[port].ipace);
+				pause_sig("pbioip", scp->pd[port].ipace);
 		}
 	}
-	return 0;
+	sx_xunlock(&scp->lock);
+	return (err);
 }
 
 static int
@@ -386,10 +393,12 @@ pbiowrite(struct cdev *dev, struct uio *uio, int ioflag)
 	port = PORT(dev);
 	scp = pbio_addr(dev);
 
+	ret = 0;
+	sx_xlock(&scp->lock);
 	while (uio->uio_resid > 0) {
 		towrite = min(uio->uio_resid, PBIO_BUFSIZ);
 		if ((ret = uiomove(scp->pd[port].buff, towrite, uio)) != 0)
-			return (ret);
+			break;
 		for (i = 0; i < towrite; i++) {
 			val = scp->pd[port].buff[i];
 			switch (port) {
@@ -413,12 +422,11 @@ pbiowrite(struct cdev *dev, struct uio *uio, int ioflag)
 				break;
 			}
 			if (scp->pd[port].opace)
-				tsleep((caddr_t)&(scp->pd[port].opace),
-					PBIOPRI, "pbioop",
-					scp->pd[port].opace);
+				pause_sig("pbioop", scp->pd[port].opace);
 		}
 	}
-	return (0);
+	sx_xunlock(&scp->lock);
+	return (ret);
 }
 
 static  int