Add a ieee80211_waitfor_parent() function that will wait for all deferred

parent interface tasks to complete. This had been added to the ioctl path but
it is also need elsewhere like detach so its safe to teardown.

Reported by:	Hans Petter Selasky
Submitted by:	sam
This commit is contained in:
thompsa 2009-02-12 18:57:18 +00:00
parent cc499f763e
commit 251dd2ca41
4 changed files with 18 additions and 2 deletions

View File

@ -289,9 +289,9 @@ ieee80211_ifdetach(struct ieee80211com *ic)
struct ifnet *ifp = ic->ic_ifp; struct ifnet *ifp = ic->ic_ifp;
struct ieee80211vap *vap; struct ieee80211vap *vap;
/* XXX ieee80211_stop_all? */
while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL) while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL)
ieee80211_vap_destroy(vap); ieee80211_vap_destroy(vap);
ieee80211_waitfor_parent(ic);
ieee80211_sysctl_detach(ic); ieee80211_sysctl_detach(ic);
ieee80211_regdomain_detach(ic); ieee80211_regdomain_detach(ic);

View File

@ -3265,7 +3265,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
} }
IEEE80211_UNLOCK(ic); IEEE80211_UNLOCK(ic);
/* Wait for parent ioctl handler if it was queued */ /* Wait for parent ioctl handler if it was queued */
taskqueue_drain(taskqueue_thread, &ic->ic_parent_task); ieee80211_waitfor_parent(ic);
break; break;
case SIOCADDMULTI: case SIOCADDMULTI:
case SIOCDELMULTI: case SIOCDELMULTI:

View File

@ -1071,6 +1071,17 @@ parent_updown(void *arg, int npending)
parent->if_ioctl(parent, SIOCSIFFLAGS, NULL); parent->if_ioctl(parent, SIOCSIFFLAGS, NULL);
} }
/*
* Block until the parent is in a known state. This is
* used after any operations that dispatch a task (e.g.
* to auto-configure the parent device up/down).
*/
void
ieee80211_waitfor_parent(struct ieee80211com *ic)
{
taskqueue_drain(taskqueue_thread, &ic->ic_parent_task);
}
/* /*
* Start a vap running. If this is the first vap to be * Start a vap running. If this is the first vap to be
* set running on the underlying device then we * set running on the underlying device then we
@ -1258,6 +1269,8 @@ ieee80211_stop_all(struct ieee80211com *ic)
ieee80211_stop_locked(vap); ieee80211_stop_locked(vap);
} }
IEEE80211_UNLOCK(ic); IEEE80211_UNLOCK(ic);
ieee80211_waitfor_parent(ic);
} }
/* /*
@ -1278,6 +1291,8 @@ ieee80211_suspend_all(struct ieee80211com *ic)
} }
} }
IEEE80211_UNLOCK(ic); IEEE80211_UNLOCK(ic);
ieee80211_waitfor_parent(ic);
} }
/* /*

View File

@ -260,6 +260,7 @@ ieee80211_gettid(const struct ieee80211_frame *wh)
return tid; return tid;
} }
void ieee80211_waitfor_parent(struct ieee80211com *);
void ieee80211_start_locked(struct ieee80211vap *); void ieee80211_start_locked(struct ieee80211vap *);
void ieee80211_init(void *); void ieee80211_init(void *);
void ieee80211_start_all(struct ieee80211com *); void ieee80211_start_all(struct ieee80211com *);