Module Name:    src
Committed By:   mrg
Date:           Thu Jan 11 06:19:49 UTC 2024

Modified Files:
        src/sys/dev/mscp: mscp.c mscp_disk.c mscp_tape.c mscpvar.h

Log Message:
mscp(4): add ability for rronline() callback in a workqueue

when an ra(4) disk comes online the hardware interrupt ends up calling
disk_set_info(), which triggers a sleep lock/alloc in this path which
is triggered by LOCKDEBUG.

piggy-back on the existing workqueue for autoconfiguration to handle
this path and run the online completion in the work queue.

this is a little ugly, in that it puts two different types of work
into the one queue, but seems less ugly than creating a second
workqueue for what is likely another one-time event (infact, the other
user may be better handled via config_defer() -- i did not look too
closely.)

with this, LOCKDEBUG kernels work.

tested in simh.


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/sys/dev/mscp/mscp.c
cvs rdiff -u -r1.90 -r1.91 src/sys/dev/mscp/mscp_disk.c
cvs rdiff -u -r1.43 -r1.44 src/sys/dev/mscp/mscp_tape.c
cvs rdiff -u -r1.18 -r1.19 src/sys/dev/mscp/mscpvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/mscp/mscp.c
diff -u src/sys/dev/mscp/mscp.c:1.38 src/sys/dev/mscp/mscp.c:1.39
--- src/sys/dev/mscp/mscp.c:1.38	Sat Aug  7 16:19:13 2021
+++ src/sys/dev/mscp/mscp.c	Thu Jan 11 06:19:49 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: mscp.c,v 1.38 2021/08/07 16:19:13 thorpej Exp $	*/
+/*	$NetBSD: mscp.c,v 1.39 2024/01/11 06:19:49 mrg Exp $	*/
 
 /*
  * Copyright (c) 1988 Regents of the University of California.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mscp.c,v 1.38 2021/08/07 16:19:13 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mscp.c,v 1.39 2024/01/11 06:19:49 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -314,6 +314,7 @@ loop:
 
 				mw->mw_mi = mi;
 				mw->mw_mp = *mp;
+				mw->mw_online = false;
 				workqueue_enqueue(mi->mi_wq,
 				    (struct work *)mw, NULL);
 			}
@@ -483,15 +484,29 @@ mscp_requeue(struct mscp_softc *mi)
 	panic("mscp_requeue");
 }
 
+/*
+ * mscp_worker: Complete configuration and online events.
+ *
+ * If the new work mw_online is false, this is an autoconfiguration
+ * event, otherwise it is a online event that needs to be handled
+ * in a thread context.
+ */
 void
-mscp_worker(struct work *wk, void *dummy)
+mscp_worker(struct work *wk, void *arg)
 {
-	struct mscp_softc *mi;
-	struct mscp_work *mw;
-	struct	drive_attach_args da;
-
-	mw = (struct mscp_work *)wk;
-	mi = mw->mw_mi;
+	struct mscp_work *mw = (struct mscp_work *)wk;
+	struct mscp_softc *mi = mw->mw_mi;
+	struct drive_attach_args da;
+
+	/* This is an online event. */
+	if (mw->mw_online) {
+		struct mscp_device *me = mi->mi_me;
+
+		if (me->me_online_cb)
+			return (*me->me_online_cb)(wk);
+		/* Must be cb for this type. */
+		panic("mscp_worker");
+	}
 
 	da.da_mp = &mw->mw_mp;
 	da.da_typ = mi->mi_type;

Index: src/sys/dev/mscp/mscp_disk.c
diff -u src/sys/dev/mscp/mscp_disk.c:1.90 src/sys/dev/mscp/mscp_disk.c:1.91
--- src/sys/dev/mscp/mscp_disk.c:1.90	Mon Aug  9 19:24:33 2021
+++ src/sys/dev/mscp/mscp_disk.c	Thu Jan 11 06:19:49 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: mscp_disk.c,v 1.90 2021/08/09 19:24:33 andvar Exp $	*/
+/*	$NetBSD: mscp_disk.c,v 1.91 2024/01/11 06:19:49 mrg Exp $	*/
 /*
  * Copyright (c) 1988 Regents of the University of California.
  * All rights reserved.
@@ -82,7 +82,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mscp_disk.c,v 1.90 2021/08/09 19:24:33 andvar Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mscp_disk.c,v 1.91 2024/01/11 06:19:49 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -112,6 +112,12 @@ __KERNEL_RCSID(0, "$NetBSD: mscp_disk.c,
 #include "ioconf.h"
 #include "ra.h"
 
+/* Embed mscp_work here, kinda ugly. */
+struct ra_work {
+	struct mscp_work ra_mw;
+	device_t ra_usc;
+};
+
 /*
  * Drive status, per drive
  */
@@ -123,6 +129,7 @@ struct ra_softc {
 	int	ra_hwunit;	/* Hardware unit number */
 	int	ra_havelabel;	/* true if we have a label */
 	int	ra_wlabel;	/* label sector is currently writable */
+	struct	ra_work ra_work;/* online callback handling */
 };
 
 #define rx_softc ra_softc
@@ -910,6 +917,7 @@ rxsize(dev_t dev)
 void	rrdgram(device_t, struct mscp *, struct mscp_softc *);
 void	rriodone(device_t, struct buf *);
 int	rronline(device_t, struct mscp *);
+void	rronline_cb(struct work *);
 int	rrgotstatus(device_t, struct mscp *);
 void	rrreplace(device_t, struct mscp *);
 int	rrioerror(device_t, struct mscp *, struct buf *);
@@ -921,6 +929,7 @@ struct	mscp_device ra_device = {
 	rrdgram,
 	rriodone,
 	rronline,
+	rronline_cb,
 	rrgotstatus,
 	rrreplace,
 	rrioerror,
@@ -962,19 +971,44 @@ rriodone(device_t usc, struct buf *bp)
 /*
  * A drive came on line.  Check its type and size.  Return DONE if
  * we think the drive is truly on line.	 In any case, awaken anyone
- * sleeping on the drive on-line-ness.
+ * sleeping on the drive on-line-ness.  We do most of this in a
+ * workqueue callback as the call to disk_set_info() will trigger a
+ * sleep lock while handling a hardware interrupt.
  */
 int
 rronline(device_t usc, struct mscp *mp)
 {
 	struct ra_softc *ra = device_private(usc);
+	device_t parent = device_parent(usc);
+	struct mscp_softc *mi;
+
+	if (!device_is_a(parent, "mscpbus"))
+		return (MSCP_FAILED);
+
+	mi = device_private(parent);
+	ra->ra_work.ra_usc = usc;
+	ra->ra_work.ra_mw.mw_mi = mi;
+	ra->ra_work.ra_mw.mw_mp = *mp;
+	ra->ra_work.ra_mw.mw_online = true;
+	workqueue_enqueue(mi->mi_wq, (struct work *)&ra->ra_work, NULL);
+
+	return (MSCP_DONE);
+}
+
+void
+rronline_cb(struct work *wk)
+{
+	struct ra_work *ra_work = (struct ra_work *)wk;
+	struct mscp *mp = &ra_work->ra_mw.mw_mp;
+	device_t usc = ra_work->ra_usc;
+	struct ra_softc *ra = device_private(usc);
 	struct disklabel *dl;
 
 	wakeup((void *)&ra->ra_state);
 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
 		aprint_error_dev(usc, "attempt to bring on line failed: ");
 		mscp_printevent(mp);
-		return (MSCP_FAILED);
+		return;
 	}
 
 	ra->ra_state = DK_OPEN;
@@ -992,8 +1026,6 @@ rronline(device_t usc, struct mscp *mp)
 	}
 	rrmakelabel(dl, ra->ra_mediaid);
 	ra_set_geometry(ra);
-
-	return (MSCP_DONE);
 }
 
 void

Index: src/sys/dev/mscp/mscp_tape.c
diff -u src/sys/dev/mscp/mscp_tape.c:1.43 src/sys/dev/mscp/mscp_tape.c:1.44
--- src/sys/dev/mscp/mscp_tape.c:1.43	Fri Jul 25 08:10:37 2014
+++ src/sys/dev/mscp/mscp_tape.c	Thu Jan 11 06:19:49 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: mscp_tape.c,v 1.43 2014/07/25 08:10:37 dholland Exp $ */
+/*	$NetBSD: mscp_tape.c,v 1.44 2024/01/11 06:19:49 mrg Exp $ */
 /*
  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mscp_tape.c,v 1.43 2014/07/25 08:10:37 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mscp_tape.c,v 1.44 2024/01/11 06:19:49 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -97,6 +97,7 @@ struct	mscp_device mt_device = {
 	mtdgram,
 	mtiodone,
 	mtonline,
+	NULL,
 	mtgotstatus,
 	0,
 	mtioerror,

Index: src/sys/dev/mscp/mscpvar.h
diff -u src/sys/dev/mscp/mscpvar.h:1.18 src/sys/dev/mscp/mscpvar.h:1.19
--- src/sys/dev/mscp/mscpvar.h:1.18	Sat Oct 27 17:18:27 2012
+++ src/sys/dev/mscp/mscpvar.h	Thu Jan 11 06:19:49 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: mscpvar.h,v 1.18 2012/10/27 17:18:27 chs Exp $	*/
+/*	$NetBSD: mscpvar.h,v 1.19 2024/01/11 06:19:49 mrg Exp $	*/
 /*
  * Copyright (c) 1988 Regents of the University of California.
  * All rights reserved.
@@ -129,6 +129,8 @@ struct	mscp_device {
 	   (device_t, struct buf *);
 	int	(*me_online)	/* drive on line */
 	   (device_t, struct mscp *);
+	void	(*me_online_cb)	/* drive on line, thread context */
+	   (struct work *wk);
 	int	(*me_gotstatus) /* got unit status */
 	   (device_t, struct mscp *);
 	void	(*me_replace)	/* replace done */
@@ -188,6 +190,7 @@ struct mscp_work {
 	struct work mw_work;
 	struct mscp_softc *mw_mi;
 	struct mscp mw_mp;
+	bool mw_online;
 	SLIST_ENTRY(mscp_work) mw_list;
 };
 

Reply via email to