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