commit 851b048ac918a05e66b2fa902a9d958ca6d1e1a5
Author: Ryota Ozaki <ozaki-r@iij.ad.jp>
Date:   Tue Apr 14 13:06:48 2015 +0900

    Use refcount(9)

diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c
index 3915a91..9333aa5 100644
--- a/sys/net/bridgestp.c
+++ b/sys/net/bridgestp.c
@@ -601,7 +601,7 @@ bstp_input(struct bridge_softc *sc, struct bridge_iflist *bif, struct mbuf *m)
 	uint16_t len;
 
 #ifdef BRIDGE_MPSAFE
-	KASSERT(bif->bif_refs > 0);
+	KASSERT(refcount_referenced_p(&bif->bif_refcount));
 #endif
 
 	eh = mtod(m, struct ether_header *);
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 41472a9..b662746 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -102,6 +102,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.97 2015/01/08 10:47:44 ozaki-r Exp $
 #include <sys/cprng.h>
 #include <sys/mutex.h>
 #include <sys/kmem.h>
+#include <sys/refcount.h>
 
 #include <net/bpf.h>
 #include <net/if.h>
@@ -773,10 +774,8 @@ bridge_try_hold_bif(struct bridge_iflist *bif)
 {
 #ifdef BRIDGE_MPSAFE
 	if (bif != NULL) {
-		if (bif->bif_waiting)
+		if (refcount_inc(&bif->bif_refcount) != 0)
 			bif = NULL;
-		else
-			atomic_inc_32(&bif->bif_refs);
 	}
 #endif
 	return bif;
@@ -791,14 +790,8 @@ static void
 bridge_release_member(struct bridge_softc *sc, struct bridge_iflist *bif)
 {
 #ifdef BRIDGE_MPSAFE
-	uint32_t refs;
-
-	refs = atomic_dec_uint_nv(&bif->bif_refs);
-	if (__predict_false(refs == 0 && bif->bif_waiting)) {
-		BRIDGE_INTR_LOCK(sc);
-		cv_broadcast(&sc->sc_iflist_cv);
-		BRIDGE_INTR_UNLOCK(sc);
-	}
+	refcount_dec_broadcast(&bif->bif_refcount, sc->sc_iflist_intr_lock,
+	    &sc->sc_iflist_cv);
 #else
 	(void)sc;
 	(void)bif;
@@ -828,15 +821,11 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif)
 	BRIDGE_UNLOCK(sc);
 
 #ifdef BRIDGE_MPSAFE
-	BRIDGE_INTR_LOCK(sc);
-	bif->bif_waiting = true;
-	membar_sync();
-	while (bif->bif_refs > 0) {
-		aprint_debug("%s: cv_wait on iflist\n", __func__);
-		cv_wait(&sc->sc_iflist_cv, sc->sc_iflist_intr_lock);
-	}
-	bif->bif_waiting = false;
-	BRIDGE_INTR_UNLOCK(sc);
+	mutex_enter(sc->sc_iflist_intr_lock);
+	refcount_dec_drain(&bif->bif_refcount, sc->sc_iflist_intr_lock,
+	    &sc->sc_iflist_cv);
+	mutex_exit(sc->sc_iflist_intr_lock);
+	refcount_fini(&bif->bif_refcount);
 #endif
 
 	kmem_free(bif, sizeof(*bif));
@@ -890,8 +879,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
 	bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
 	bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
 	bif->bif_path_cost = BSTP_DEFAULT_PATH_COST;
-	bif->bif_refs = 0;
-	bif->bif_waiting = false;
+	refcount_init(&bif->bif_refcount);
 
 	BRIDGE_LOCK(sc);
 
@@ -926,8 +914,8 @@ bridge_ioctl_del(struct bridge_softc *sc, void *arg)
 	BRIDGE_LOCK(sc);
 
 	/*
-	 * Don't use bridge_lookup_member. We want to get a member
-	 * with bif_refs == 0.
+	 * Don't use bridge_lookup_member to get a member
+	 * without incrementing refcount.
 	 */
 	LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 		ifs = bif->bif_ifp;
diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h
index 4bdecab..0f41e6e9 100644
--- a/sys/net/if_bridgevar.h
+++ b/sys/net/if_bridgevar.h
@@ -79,6 +79,7 @@
 #include <sys/queue.h>
 #include <sys/mutex.h>
 #include <sys/condvar.h>
+#include <sys/refcount.h>
 
 /*
  * Commands used in the SIOCSDRVSPEC ioctl.  Note the lookup of the
@@ -264,8 +265,7 @@ struct bridge_iflist {
 	uint8_t			bif_priority;
 	struct ifnet		*bif_ifp;	/* member if */
 	uint32_t		bif_flags;	/* member if flags */
-	uint32_t		bif_refs;	/* reference count */
-	bool			bif_waiting;	/* waiting for released  */
+	struct refcount		bif_refcount;	/* reference count */
 };
 
 /*