Index: sys/systm.h
===================================================================
RCS file: /cvsroot/src/sys/sys/systm.h,v
retrieving revision 1.239
diff -u -r1.239 systm.h
--- sys/systm.h	31 Jan 2010 02:04:43 -0000	1.239
+++ sys/systm.h	18 May 2010 22:01:26 -0000
@@ -362,6 +362,10 @@
 void	mountroothook_destroy(void);
 void	domountroothook(struct device *);
 
+void	*aftermountroothook_establish(void (*)(struct device *), struct device *);
+void	aftermountroothook_disestablish(void *);
+void	doaftermountroothook(void);
+
 /*
  * Exec hooks. Subsystems may want to do cleanup when a process
  * execs.
Index: kern/init_main.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_main.c,v
retrieving revision 1.419
diff -u -r1.419 init_main.c
--- kern/init_main.c	21 Apr 2010 16:51:24 -0000	1.419
+++ kern/init_main.c	18 May 2010 22:01:26 -0000
@@ -682,6 +682,8 @@
 	    uvm_aiodone_worker, NULL, PRI_VM, IPL_NONE, WQ_MPSAFE))
 		panic("fork aiodoned");
 
+	doaftermountroothook();
+
 	/*
 	 * Okay, now we can let init(8) exec!  It's off to userland!
 	 */
Index: kern/kern_hook.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_hook.c,v
retrieving revision 1.3
diff -u -r1.3 kern_hook.c
--- kern/kern_hook.c	31 Jan 2010 09:27:40 -0000	1.3
+++ kern/kern_hook.c	18 May 2010 22:01:26 -0000
@@ -196,6 +196,37 @@
 	}
 }
 
+/*
+ * "After mountroot hook" types, functions, and variables.
+ */
+
+static hook_list_t aftermountroothook_list =
+    LIST_HEAD_INITIALIZER(aftermountroothook_list);
+
+void *
+aftermountroothook_establish(void (*fn)(device_t), device_t dev)
+{
+	return hook_establish(&aftermountroothook_list, (void (*)(void *))fn, dev);
+}
+
+void
+aftermountroothook_disestablish(void *vhook)
+{
+	hook_disestablish(&aftermountroothook_list, vhook);
+}
+
+void
+doaftermountroothook(void)
+{
+	struct hook_desc *hd;
+
+	while ((hd = LIST_FIRST(&aftermountroothook_list)) != NULL) {
+		LIST_REMOVE(hd, hk_list);
+		(*hd->hk_fn)(hd->hk_arg);
+		free(hd, M_DEVBUF);
+	}
+}
+
 static hook_list_t exechook_list = LIST_HEAD_INITIALIZER(exechook_list);
 
 void *
Index: dev/usb/if_zyd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_zyd.c,v
retrieving revision 1.25
diff -u -r1.25 if_zyd.c
--- dev/usb/if_zyd.c	5 Apr 2010 07:21:49 -0000	1.25
+++ dev/usb/if_zyd.c	21 May 2010 14:26:49 -0000
@@ -156,7 +156,7 @@
 CFATTACH_DECL_NEW(zyd, sizeof(struct zyd_softc), zyd_match,
     zyd_attach, zyd_detach, zyd_activate);
 
-Static int	zyd_attachhook(void *);
+Static void	zyd_attachhook(device_t);
 Static int	zyd_complete_attach(struct zyd_softc *);
 Static int	zyd_open_pipes(struct zyd_softc *);
 Static void	zyd_close_pipes(struct zyd_softc *);
@@ -245,10 +245,10 @@
 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
 }
 
-Static int
-zyd_attachhook(void *xsc)
+Static void
+zyd_attachhook(device_t dv)
 {
-	struct zyd_softc *sc = xsc;
+	struct zyd_softc *sc = device_private(dv);
 	firmware_handle_t fwh;
 	const char *fwname;
 	u_char *fw;
@@ -259,7 +259,7 @@
 	if ((error = firmware_open("zyd", fwname, &fwh)) != 0) {
 		aprint_error_dev(sc->sc_dev,
 		    "failed to open firmware %s (error=%d)\n", fwname, error);
-		return error;
+		return;
 	}
 	size = firmware_get_size(fwh);
 	fw = firmware_malloc(size);
@@ -267,7 +267,7 @@
 		aprint_error_dev(sc->sc_dev,
 		    "failed to allocate firmware memory\n");
 		firmware_close(fwh);
-		return ENOMEM;
+		return;
 	}
 	error = firmware_read(fwh, 0, fw, size);
 	firmware_close(fwh);
@@ -275,7 +275,7 @@
 		aprint_error_dev(sc->sc_dev,
 		    "failed to read firmware (error %d)\n", error);
 		firmware_free(fw, 0);
-		return error;
+		return;
 	}
 
 	error = zyd_loadfirmware(sc, fw, size);
@@ -283,16 +283,15 @@
 		aprint_error_dev(sc->sc_dev,
 		    "could not load firmware (error=%d)\n", error);
 		firmware_free(fw, 0);
-		return ENXIO;
+		return;
 	}
 
 	firmware_free(fw, 0);
 	sc->sc_flags |= ZD1211_FWLOADED;
 
 	/* complete the attach process */
-	if ((error = zyd_complete_attach(sc)) == 0)
+	if (zyd_complete_attach(sc) == 0)
 		sc->attached = 1;
-	return error;
 }
 
 void
@@ -334,13 +333,12 @@
 	IFQ_SET_READY(&ifp->if_snd);
 	memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
 
-	if_attach(ifp);
-	/* XXXX: alloc temporarily until the layer2 can be configured. */
-	if_alloc_sadl(ifp);
-
 	SIMPLEQ_INIT(&sc->sc_rqh);
 
-	return;
+	if (rootvp == NULL)
+		aftermountroothook_establish(zyd_attachhook, self);
+	else
+		zyd_attachhook(self);
 }
 
 Static int
@@ -424,7 +422,7 @@
 		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
 	}
 
-	if_free_sadl(ifp);
+	if_attach(ifp);
 	ieee80211_ifattach(ic);
 	ic->ic_node_alloc = zyd_node_alloc;
 	ic->ic_newassoc = zyd_newassoc;
@@ -461,11 +459,8 @@
 	struct ifnet *ifp = &sc->sc_if;
 	int s;
 
-	if (!sc->attached) {
-		if_free_sadl(ifp);
-		if_detach(ifp);
+	if (!sc->attached)
 		return 0;
-	}
 
 	s = splusb();
 
@@ -2450,10 +2445,6 @@
 	struct ieee80211com *ic = &sc->sc_ic;
 	int i, error;
 
-	if ((sc->sc_flags & ZD1211_FWLOADED) == 0)
-		if ((error = zyd_attachhook(sc)) != 0)
-			return error;
-
 	zyd_stop(ifp, 0);
 
 	IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
