--- a/net80211/ieee80211_proto.c
+++ b/net80211/ieee80211_proto.c
-@@ -1348,7 +1348,7 @@
+@@ -1348,7 +1348,7 @@ __ieee80211_newstate(struct ieee80211vap
IEEE80211_SEND_MGMT(ni,
IEEE80211_FC0_SUBTYPE_DISASSOC,
IEEE80211_REASON_ASSOC_LEAVE);
break;
case IEEE80211_M_HOSTAP:
ieee80211_iterate_nodes(&ic->ic_sta,
-@@ -1358,6 +1358,7 @@
+@@ -1358,12 +1358,14 @@ __ieee80211_newstate(struct ieee80211vap
break;
}
goto reset;
case IEEE80211_S_ASSOC:
switch (vap->iv_opmode) {
case IEEE80211_M_STA:
-@@ -1376,7 +1377,6 @@
+ IEEE80211_SEND_MGMT(ni,
+ IEEE80211_FC0_SUBTYPE_DEAUTH,
+ IEEE80211_REASON_AUTH_LEAVE);
++ ieee80211_node_leave(ni);
+ break;
+ case IEEE80211_M_HOSTAP:
+ ieee80211_iterate_nodes(&ic->ic_sta,
+@@ -1376,7 +1378,6 @@ __ieee80211_newstate(struct ieee80211vap
case IEEE80211_S_SCAN:
ieee80211_cancel_scan(vap);
goto reset;
reset:
ieee80211_reset_bss(vap);
break;
-@@ -1432,7 +1432,7 @@
+@@ -1429,10 +1430,12 @@ __ieee80211_newstate(struct ieee80211vap
+ IEEE80211_SCAN_FOREVER,
+ vap->iv_des_nssid, vap->iv_des_ssid,
+ NULL);
++ else
++ ieee80211_node_leave(vap->iv_bss);
break;
case IEEE80211_S_RUN: /* beacon miss */
if (vap->iv_opmode == IEEE80211_M_STA) {
vap->iv_flags &= ~IEEE80211_F_SIBSS; /* XXX */
if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
ieee80211_check_scan(vap,
-@@ -1483,7 +1483,7 @@
- vap->iv_state = ostate; /* stay RUN */
- break;
- case IEEE80211_FC0_SUBTYPE_DEAUTH:
-- ieee80211_sta_leave(ni);
-+ ieee80211_node_leave(ni);
- if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
- /* try to reauth */
- IEEE80211_SEND_MGMT(ni,
-@@ -1510,7 +1510,7 @@
+@@ -1511,7 +1514,7 @@ __ieee80211_newstate(struct ieee80211vap
IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
break;
case IEEE80211_S_RUN:
if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
/* NB: caller specifies ASSOC/REASSOC by arg */
IEEE80211_SEND_MGMT(ni, arg ?
+@@ -1779,6 +1782,7 @@ ieee80211_newstate(struct ieee80211vap *
+ ieee80211_state_name[nstate],
+ ieee80211_state_name[dstate]);
+
++ ieee80211_update_link_status(vap, nstate, ostate);
+ switch (nstate) {
+ case IEEE80211_S_AUTH:
+ case IEEE80211_S_ASSOC:
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -233,33 +233,59 @@ ieee80211_vlan_vdetach(struct ieee80211v
+ }
+
+ void
+-ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
++ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate)
+ {
+- struct ieee80211vap *vap = ni->ni_vap;
+ struct net_device *dev = vap->iv_dev;
+ union iwreq_data wreq;
++ int active;
++
++ if (vap->iv_opmode != IEEE80211_M_STA)
++ return;
++
++ if (ostate == nstate)
++ return;
++
++ if (nstate == IEEE80211_S_RUN)
++ active = 1;
++ else if ((ostate >= IEEE80211_S_AUTH) && (nstate < ostate))
++ active = 0;
++ else
++ return;
++
++ if (active && !vap->iv_bss)
++ return;
++
++ memset(&wreq, 0, sizeof(wreq));
++ wreq.ap_addr.sa_family = ARPHRD_ETHER;
+
+- if (ni == vap->iv_bss) {
+- if (newassoc)
+- netif_carrier_on(dev);
+- memset(&wreq, 0, sizeof(wreq));
++ if (active) {
++ //netif_carrier_on(vap->iv_dev);
+ IEEE80211_ADDR_COPY(wreq.addr.sa_data, vap->iv_bssid);
+- wreq.addr.sa_family = ARPHRD_ETHER;
+-#ifdef ATH_SUPERG_XR
+- if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
+- dev = vap->iv_xrvap->iv_dev;
+-#endif
+- wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
+ } else {
+- memset(&wreq, 0, sizeof(wreq));
+- IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
+- wreq.addr.sa_family = ARPHRD_ETHER;
++ //netif_carrier_off(vap->iv_dev);
++ memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
++ }
++ wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
++}
++
++void
++ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
++{
++ struct ieee80211vap *vap = ni->ni_vap;
++ struct net_device *dev = vap->iv_dev;
++ union iwreq_data wreq;
++
++ if (ni == vap->iv_bss)
++ return;
++
++ memset(&wreq, 0, sizeof(wreq));
++ IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
++ wreq.addr.sa_family = ARPHRD_ETHER;
+ #ifdef ATH_SUPERG_XR
+- if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
+- dev = vap->iv_xrvap->iv_dev;
++ if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
++ dev = vap->iv_xrvap->iv_dev;
+ #endif
+- wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
+- }
++ wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
+ }
+
+ void
+@@ -269,18 +295,14 @@ ieee80211_notify_node_leave(struct ieee8
+ struct net_device *dev = vap->iv_dev;
+ union iwreq_data wreq;
+
+- if (ni == vap->iv_bss) {
+- netif_carrier_off(dev);
+- memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
+- wreq.ap_addr.sa_family = ARPHRD_ETHER;
+- wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
+- } else {
+- /* fire off wireless event station leaving */
+- memset(&wreq, 0, sizeof(wreq));
+- IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
+- wreq.addr.sa_family = ARPHRD_ETHER;
+- wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
+- }
++ if (ni == vap->iv_bss)
++ return;
++
++ /* fire off wireless event station leaving */
++ memset(&wreq, 0, sizeof(wreq));
++ IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
++ wreq.addr.sa_family = ARPHRD_ETHER;
++ wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
+ }
+
+ void
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -2332,6 +2332,7 @@ ieee80211_node_leave(struct ieee80211_no
+ count_suppchans(ic, ni, -1);
+ IEEE80211_UNLOCK_IRQ(ic);
+
++done:
+ /*
+ * Cleanup station state. In particular clear various
+ * state that might otherwise be reused if the node
+@@ -2339,7 +2340,7 @@ ieee80211_node_leave(struct ieee80211_no
+ * (and memory is reclaimed).
+ */
+ ieee80211_sta_leave(ni);
+-done:
++
+ /* Run a cleanup */
+ #ifdef IEEE80211_DEBUG_REFCNT
+ ic->ic_node_cleanup_debug(ni, __func__, __LINE__);
+--- a/net80211/ieee80211_node.h
++++ b/net80211/ieee80211_node.h
+@@ -60,7 +60,7 @@
+ #define IEEE80211_INACT_PROBE (30/IEEE80211_INACT_WAIT) /* probe */
+ #define IEEE80211_INACT_SCAN (300/IEEE80211_INACT_WAIT) /* scanned */
+
+-#define IEEE80211_TRANS_WAIT 5 /* mgt frame tx timer (secs) */
++#define IEEE80211_TRANS_WAIT 300 /* mgt frame tx timer (msecs) */
+
+ #define IEEE80211_NODE_HASHSIZE 32
+ /* simple hash is enough for variation of macaddr */
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -2141,7 +2141,7 @@ ieee80211_send_mgmt(struct ieee80211_nod
+
+ ieee80211_mgmt_output(ieee80211_ref_node(ni), skb, type);
+ if (timer)
+- mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ);
++ mod_timer(&vap->iv_mgtsend, jiffies + msecs_to_jiffies(timer));
+ return 0;
+ bad:
+ return ret;
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -514,8 +514,9 @@ ieee80211_ioctl_siwap(struct net_device
+ vap->iv_flags |= IEEE80211_F_DESBSSID;
+
+ IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data);
+- if (IS_UP_AUTO(vap))
++ if (IS_UP(vap->iv_dev)) {
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
++ }
+ }
+ return 0;
+ }
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -643,6 +643,7 @@ void ieee80211_vlan_vdetach(struct ieee8
+ #define free_netdev(dev) kfree(dev)
+ #endif
+
++void ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate);
+ void ieee80211_ioctl_vattach(struct ieee80211vap *);
+ void ieee80211_ioctl_vdetach(struct ieee80211vap *);
+ struct ifreq;