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;
};