summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net80211/ieee80211_freebsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/net80211/ieee80211_freebsd.c')
-rw-r--r--freebsd/sys/net80211/ieee80211_freebsd.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/freebsd/sys/net80211/ieee80211_freebsd.c b/freebsd/sys/net80211/ieee80211_freebsd.c
index 00430f77..57e2f23f 100644
--- a/freebsd/sys/net80211/ieee80211_freebsd.c
+++ b/freebsd/sys/net80211/ieee80211_freebsd.c
@@ -309,6 +309,55 @@ ieee80211_sysctl_vdetach(struct ieee80211vap *vap)
}
}
+#define MS(_v, _f) (((_v) & _f##_M) >> _f##_S)
+int
+ieee80211_com_vincref(struct ieee80211vap *vap)
+{
+ uint32_t ostate;
+
+ ostate = atomic_fetchadd_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
+
+ if (ostate & IEEE80211_COM_DETACHED) {
+ atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
+ return (ENETDOWN);
+ }
+
+ if (MS(ostate, IEEE80211_COM_REF) == IEEE80211_COM_REF_MAX) {
+ atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
+ return (EOVERFLOW);
+ }
+
+ return (0);
+}
+
+void
+ieee80211_com_vdecref(struct ieee80211vap *vap)
+{
+ uint32_t ostate;
+
+ ostate = atomic_fetchadd_32(&vap->iv_com_state, -IEEE80211_COM_REF_ADD);
+
+ KASSERT(MS(ostate, IEEE80211_COM_REF) != 0,
+ ("com reference counter underflow"));
+
+ (void) ostate;
+}
+
+void
+ieee80211_com_vdetach(struct ieee80211vap *vap)
+{
+ int sleep_time;
+
+ sleep_time = msecs_to_ticks(250);
+ if (sleep_time == 0)
+ sleep_time = 1;
+
+ atomic_set_32(&vap->iv_com_state, IEEE80211_COM_DETACHED);
+ while (MS(atomic_load_32(&vap->iv_com_state), IEEE80211_COM_REF) != 0)
+ pause("comref", sleep_time);
+}
+#undef MS
+
int
ieee80211_node_dectestref(struct ieee80211_node *ni)
{