? sys/dev/mscp/.mscp.c.swp
? sys/dev/mscp/.mscp_subr.c.swp
? sys/dev/mscp/.mscpvar.h.swp
Index: sys/dev/mscp/mscp.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mscp/mscp.c,v
retrieving revision 1.29
diff -u -r1.29 mscp.c
--- sys/dev/mscp/mscp.c 8 Apr 2008 20:10:44 -0000       1.29
+++ sys/dev/mscp/mscp.c 11 Jan 2009 01:02:27 -0000
@@ -86,6 +86,7 @@
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/systm.h>
+#include <sys/kmem.h>

#include <sys/bus.h>

@@ -95,6 +96,13 @@

#define PCMD   PSWP            /* priority for command packet waits */

+/* An mscp workqueue item */
+struct mscp_work {
+       struct work mw_work;
+       struct mscp_softc *mw_mi;
+       struct mscp mw_mp;
+};
+
/*
 * Get a command packet.  Second argument is true iff we are
 * to wait if necessary.  Return NULL if none are available and
@@ -297,11 +305,19 @@
                       break;

               if (drive == 0) {
-                       struct  drive_attach_args da;
+                       struct mscp_work *mw;
+
+                       mw = kmem_zalloc(sizeof(*mw), KM_NOSLEEP);
+                       if (mw == NULL) {
+                               aprint_error_dev(&mi->mi_dev,
+                                       "out of memory, cannot attach\n");
+                               return;
+                       }

-                       da.da_mp = (struct mscp *)mp;
-                       da.da_typ = mi->mi_type;
-                       config_found(&mi->mi_dev, (void *)&da, mscp_print);
+                       mw->mw_mi = mi;
+                       mw->mw_mp = *mp;
+
+                       workqueue_enqueue(mi->mi_wq, (struct work *)mw, NULL);
               } else
                       /* Hack to avoid complaints */
                       if (!(((mp->mscp_event & M_ST_MASK) == M_ST_AVAILABLE)
@@ -469,3 +485,16 @@
       panic("mscp_requeue");
}

+void
+mscp_worker(struct work *wk, void *dummy)
+{
+       struct mscp_work *mw = (struct mscp_work *)wk;
+       struct drive_attach_args da;
+
+       da.da_mp = &mw->mw_mp;
+       da.da_typ = mw->mw_mi->mi_type;
+
+       config_found(&mw->mw_mi->mi_dev, (void *)&da, mscp_print);
+
+       kmem_free(mw, sizeof(*mw));
+}
Index: sys/dev/mscp/mscp_subr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mscp/mscp_subr.c,v
retrieving revision 1.35
diff -u -r1.35 mscp_subr.c
--- sys/dev/mscp/mscp_subr.c    8 Apr 2008 20:10:44 -0000       1.35
+++ sys/dev/mscp/mscp_subr.c    11 Jan 2009 01:02:28 -0000
@@ -226,6 +226,11 @@
               mi->mi_me = &mt_device;
       }
#endif
+
+       if (workqueue_create(&mi->mi_wq, "mscp_wq", mscp_worker, NULL,
+           PRI_NONE, IPL_NONE, 0) != 0)
+               panic("%s: could not create workqueue", __func__);
+
       /*
        * Go out and search for sub-units on this MSCP bus,
        * and call config_found for each found.
Index: sys/dev/mscp/mscpvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mscp/mscpvar.h,v
retrieving revision 1.15
diff -u -r1.15 mscpvar.h
--- sys/dev/mscp/mscpvar.h      4 Mar 2007 06:02:14 -0000       1.15
+++ sys/dev/mscp/mscpvar.h      11 Jan 2009 01:02:28 -0000
@@ -70,6 +70,8 @@
 *     @(#)mscpvar.h   7.3 (Berkeley) 6/28/90
 */

+#include <sys/workqueue.h>
+
/*
 * MSCP generic driver configuration
 */
@@ -224,6 +226,7 @@
       bus_space_handle_t mi_sah;      /* status & address (read part) */
       bus_space_handle_t mi_swh;      /* status & address (write part) */
       struct bufq_state *mi_resq;     /* While waiting for packets */
+       struct workqueue *mi_wq;        /* Workqueue for autoconf work */
};

/* mi_flags */
@@ -280,3 +283,4 @@
int    mscp_waitstep(struct mscp_softc *, int, int);
void   mscp_dgo(struct mscp_softc *, struct mscp_xi *);
void   mscp_intr(struct mscp_softc *);
+void   mscp_worker(struct work *, void *);