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.
This commit is contained in:
parent
75b2f6328c
commit
9eaecdf176
|
@ -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;
|
||||
struct mscp_work *mw = (struct mscp_work *)wk;
|
||||
struct mscp_softc *mi = mw->mw_mi;
|
||||
struct drive_attach_args da;
|
||||
|
||||
mw = (struct mscp_work *)wk;
|
||||
mi = mw->mw_mi;
|
||||
/* 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;
|
||||
|
|
|
@ -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,v 1.90 2021/08/09 19:24:33 andvar Exp $"
|
|||
#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,11 +971,36 @@ 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;
|
||||
|
||||
|
@ -974,7 +1008,7 @@ rronline(device_t usc, struct mscp *mp)
|
|||
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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue