aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-10 09:29:03 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-24 15:05:10 -0400
commitb291ba11181d46dfbd2d7a5c00a5f3335228191e (patch)
tree47813dce4a42e8334e531417425aa861848802bd /net/mac80211
parentca386f3137eb68621fadba546d9eb35ac2f82de3 (diff)
mac80211: monitor the connection
With the recent MLME rework I accidentally removed the connection monitoring code. In order to add it back, this patch will add new code to monitor both for beacon loss and for the connection actually working, with possibly separate triggers. When no unicast frames have been received from the AP for (currently) two seconds, we will send the AP a probe request. Also, when we don't see beacons from the AP for two seconds, we do the same (but those times need not be the same due to the way the code is now written). Additionally, clean up the parameters to the ieee80211_set_disassoc() function that I need here, those are all useless except sdata. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h20
-rw-r--r--net/mac80211/mlme.c257
-rw-r--r--net/mac80211/rx.c22
3 files changed, 227 insertions, 72 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 06b3411530f2..a34bca2dc52f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -256,12 +256,13 @@ struct ieee80211_mgd_work {
256 256
257/* flags used in struct ieee80211_if_managed.flags */ 257/* flags used in struct ieee80211_if_managed.flags */
258enum ieee80211_sta_flags { 258enum ieee80211_sta_flags {
259 IEEE80211_STA_PROBEREQ_POLL = BIT(3), 259 IEEE80211_STA_BEACON_POLL = BIT(0),
260 IEEE80211_STA_CONTROL_PORT = BIT(4), 260 IEEE80211_STA_CONNECTION_POLL = BIT(1),
261 IEEE80211_STA_WMM_ENABLED = BIT(5), 261 IEEE80211_STA_CONTROL_PORT = BIT(2),
262 IEEE80211_STA_DISABLE_11N = BIT(6), 262 IEEE80211_STA_WMM_ENABLED = BIT(3),
263 IEEE80211_STA_CSA_RECEIVED = BIT(7), 263 IEEE80211_STA_DISABLE_11N = BIT(4),
264 IEEE80211_STA_MFP_ENABLED = BIT(8), 264 IEEE80211_STA_CSA_RECEIVED = BIT(5),
265 IEEE80211_STA_MFP_ENABLED = BIT(6),
265}; 266};
266 267
267/* flags for MLME request */ 268/* flags for MLME request */
@@ -271,11 +272,16 @@ enum ieee80211_sta_request {
271 272
272struct ieee80211_if_managed { 273struct ieee80211_if_managed {
273 struct timer_list timer; 274 struct timer_list timer;
275 struct timer_list conn_mon_timer;
276 struct timer_list bcn_mon_timer;
274 struct timer_list chswitch_timer; 277 struct timer_list chswitch_timer;
275 struct work_struct work; 278 struct work_struct work;
279 struct work_struct monitor_work;
276 struct work_struct chswitch_work; 280 struct work_struct chswitch_work;
277 struct work_struct beacon_loss_work; 281 struct work_struct beacon_loss_work;
278 282
283 unsigned long probe_timeout;
284
279 struct mutex mtx; 285 struct mutex mtx;
280 struct ieee80211_bss *associated; 286 struct ieee80211_bss *associated;
281 struct list_head work_list; 287 struct list_head work_list;
@@ -292,8 +298,6 @@ struct ieee80211_if_managed {
292 298
293 unsigned long request; 299 unsigned long request;
294 300
295 unsigned long last_beacon;
296
297 unsigned int flags; 301 unsigned int flags;
298 302
299 u32 beacon_crc; 303 u32 beacon_crc;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c1114bb8095b..18dad229344c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -31,8 +31,23 @@
31#define IEEE80211_AUTH_MAX_TRIES 3 31#define IEEE80211_AUTH_MAX_TRIES 3
32#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) 32#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
33#define IEEE80211_ASSOC_MAX_TRIES 3 33#define IEEE80211_ASSOC_MAX_TRIES 3
34#define IEEE80211_MONITORING_INTERVAL (2 * HZ) 34
35#define IEEE80211_PROBE_WAIT (HZ / 5) 35/*
36 * beacon loss detection timeout
37 * XXX: should depend on beacon interval
38 */
39#define IEEE80211_BEACON_LOSS_TIME (2 * HZ)
40/*
41 * Time the connection can be idle before we probe
42 * it to see if we can still talk to the AP.
43 */
44#define IEEE80211_CONNECTION_IDLE_TIME (2 * HZ)
45/*
46 * Time we wait for a probe response after sending
47 * a probe request because of beacon loss or for
48 * checking the connection still works.
49 */
50#define IEEE80211_PROBE_WAIT (HZ / 5)
36 51
37#define TMR_RUNNING_TIMER 0 52#define TMR_RUNNING_TIMER 0
38#define TMR_RUNNING_CHANSW 1 53#define TMR_RUNNING_CHANSW 1
@@ -92,6 +107,15 @@ static void run_again(struct ieee80211_if_managed *ifmgd,
92 mod_timer(&ifmgd->timer, timeout); 107 mod_timer(&ifmgd->timer, timeout);
93} 108}
94 109
110static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata)
111{
112 if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER)
113 return;
114
115 mod_timer(&sdata->u.mgd.bcn_mon_timer,
116 round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME));
117}
118
95static int ecw2cw(int ecw) 119static int ecw2cw(int ecw)
96{ 120{
97 return (1 << ecw) - 1; 121 return (1 << ecw) - 1;
@@ -666,7 +690,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
666 690
667 if (count == 1 && found->u.mgd.powersave && 691 if (count == 1 && found->u.mgd.powersave &&
668 found->u.mgd.associated && list_empty(&found->u.mgd.work_list) && 692 found->u.mgd.associated && list_empty(&found->u.mgd.work_list) &&
669 !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) { 693 !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
694 IEEE80211_STA_CONNECTION_POLL))) {
670 s32 beaconint_us; 695 s32 beaconint_us;
671 696
672 if (latency < 0) 697 if (latency < 0)
@@ -872,6 +897,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
872 sdata->u.mgd.associated = bss; 897 sdata->u.mgd.associated = bss;
873 memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); 898 memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
874 899
900 /* just to be sure */
901 sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
902 IEEE80211_STA_BEACON_POLL);
903
875 ieee80211_led_assoc(local, 1); 904 ieee80211_led_assoc(local, 1);
876 905
877 sdata->vif.bss_conf.assoc = 1; 906 sdata->vif.bss_conf.assoc = 1;
@@ -983,16 +1012,21 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
983 return RX_MGMT_NONE; 1012 return RX_MGMT_NONE;
984} 1013}
985 1014
986static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, 1015static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
987 const u8 *bssid, bool deauth)
988{ 1016{
989 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1017 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
990 struct ieee80211_local *local = sdata->local; 1018 struct ieee80211_local *local = sdata->local;
991 struct sta_info *sta; 1019 struct sta_info *sta;
992 u32 changed = 0, config_changed = 0; 1020 u32 changed = 0, config_changed = 0;
1021 u8 bssid[ETH_ALEN];
993 1022
994 ASSERT_MGD_MTX(ifmgd); 1023 ASSERT_MGD_MTX(ifmgd);
995 1024
1025 if (WARN_ON(!ifmgd->associated))
1026 return;
1027
1028 memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
1029
996 ifmgd->associated = NULL; 1030 ifmgd->associated = NULL;
997 memset(ifmgd->bssid, 0, ETH_ALEN); 1031 memset(ifmgd->bssid, 0, ETH_ALEN);
998 1032
@@ -1112,32 +1146,22 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1112 * from AP because we know that the connection is working both ways 1146 * from AP because we know that the connection is working both ways
1113 * at that time. But multicast frames (and hence also beacons) must 1147 * at that time. But multicast frames (and hence also beacons) must
1114 * be ignored here, because we need to trigger the timer during 1148 * be ignored here, because we need to trigger the timer during
1115 * data idle periods for sending the periodical probe request to 1149 * data idle periods for sending the periodic probe request to the
1116 * the AP. 1150 * AP we're connected to.
1117 */ 1151 */
1118 if (!is_multicast_ether_addr(hdr->addr1)) 1152 if (is_multicast_ether_addr(hdr->addr1))
1119 mod_timer(&sdata->u.mgd.timer, 1153 return;
1120 jiffies + IEEE80211_MONITORING_INTERVAL); 1154
1155 mod_timer(&sdata->u.mgd.conn_mon_timer,
1156 round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
1121} 1157}
1122 1158
1123void ieee80211_beacon_loss_work(struct work_struct *work) 1159static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
1160 bool beacon)
1124{ 1161{
1125 struct ieee80211_sub_if_data *sdata =
1126 container_of(work, struct ieee80211_sub_if_data,
1127 u.mgd.beacon_loss_work);
1128 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1162 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1129 const u8 *ssid; 1163 const u8 *ssid;
1130 1164 bool already = false;
1131 /*
1132 * The driver has already reported this event and we have
1133 * already sent a probe request. Maybe the AP died and the
1134 * driver keeps reporting until we disassociate... We have
1135 * to ignore that because otherwise we would continually
1136 * reset the timer and never check whether we received a
1137 * probe response!
1138 */
1139 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
1140 return;
1141 1165
1142 mutex_lock(&ifmgd->mtx); 1166 mutex_lock(&ifmgd->mtx);
1143 1167
@@ -1145,12 +1169,35 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
1145 goto out; 1169 goto out;
1146 1170
1147#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 1171#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1148 if (net_ratelimit()) 1172 if (beacon && net_ratelimit())
1149 printk(KERN_DEBUG "%s: driver reports beacon loss from AP " 1173 printk(KERN_DEBUG "%s: detected beacon loss from AP "
1150 "- sending probe request\n", sdata->dev->name); 1174 "- sending probe request\n", sdata->dev->name);
1151#endif 1175#endif
1152 1176
1153 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; 1177 /*
1178 * The driver/our work has already reported this event or the
1179 * connection monitoring has kicked in and we have already sent
1180 * a probe request. Or maybe the AP died and the driver keeps
1181 * reporting until we disassociate...
1182 *
1183 * In either case we have to ignore the current call to this
1184 * function (except for setting the correct probe reason bit)
1185 * because otherwise we would reset the timer every time and
1186 * never check whether we received a probe response!
1187 */
1188 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
1189 IEEE80211_STA_CONNECTION_POLL))
1190 already = true;
1191
1192 if (beacon)
1193 ifmgd->flags |= IEEE80211_STA_BEACON_POLL;
1194 else
1195 ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL;
1196
1197 if (already)
1198 goto out;
1199
1200 ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
1154 1201
1155 mutex_lock(&sdata->local->iflist_mtx); 1202 mutex_lock(&sdata->local->iflist_mtx);
1156 ieee80211_recalc_ps(sdata->local, -1); 1203 ieee80211_recalc_ps(sdata->local, -1);
@@ -1160,11 +1207,21 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
1160 ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, 1207 ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid,
1161 ssid + 2, ssid[1], NULL, 0); 1208 ssid + 2, ssid[1], NULL, 0);
1162 1209
1163 run_again(ifmgd, jiffies + IEEE80211_PROBE_WAIT); 1210 run_again(ifmgd, ifmgd->probe_timeout);
1211
1164 out: 1212 out:
1165 mutex_unlock(&ifmgd->mtx); 1213 mutex_unlock(&ifmgd->mtx);
1166} 1214}
1167 1215
1216void ieee80211_beacon_loss_work(struct work_struct *work)
1217{
1218 struct ieee80211_sub_if_data *sdata =
1219 container_of(work, struct ieee80211_sub_if_data,
1220 u.mgd.beacon_loss_work);
1221
1222 ieee80211_mgd_probe_ap(sdata, true);
1223}
1224
1168void ieee80211_beacon_loss(struct ieee80211_vif *vif) 1225void ieee80211_beacon_loss(struct ieee80211_vif *vif)
1169{ 1226{
1170 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1227 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
@@ -1278,7 +1335,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1278 sdata->dev->name, bssid, reason_code); 1335 sdata->dev->name, bssid, reason_code);
1279 1336
1280 if (!wk) { 1337 if (!wk) {
1281 ieee80211_set_disassoc(sdata, bssid, true); 1338 ieee80211_set_disassoc(sdata);
1282 } else { 1339 } else {
1283 list_del(&wk->list); 1340 list_del(&wk->list);
1284 kfree(wk); 1341 kfree(wk);
@@ -1311,7 +1368,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1311 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", 1368 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
1312 sdata->dev->name, reason_code); 1369 sdata->dev->name, reason_code);
1313 1370
1314 ieee80211_set_disassoc(sdata, ifmgd->associated->cbss.bssid, false); 1371 ieee80211_set_disassoc(sdata);
1315 return RX_MGMT_CFG80211_DISASSOC; 1372 return RX_MGMT_CFG80211_DISASSOC;
1316} 1373}
1317 1374
@@ -1412,9 +1469,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1412 return RX_MGMT_NONE; 1469 return RX_MGMT_NONE;
1413 } 1470 }
1414 1471
1415 /* update new sta with its last rx activity */
1416 sta->last_rx = jiffies;
1417
1418 set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | 1472 set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
1419 WLAN_STA_ASSOC_AP); 1473 WLAN_STA_ASSOC_AP);
1420 if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) 1474 if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
@@ -1517,10 +1571,11 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1517 ieee80211_set_associated(sdata, wk->bss, changed); 1571 ieee80211_set_associated(sdata, wk->bss, changed);
1518 1572
1519 /* 1573 /*
1520 * initialise the time of last beacon to be the association time, 1574 * Start timer to probe the connection to the AP now.
1521 * otherwise beacon loss check will trigger immediately 1575 * Also start the timer that will detect beacon loss.
1522 */ 1576 */
1523 ifmgd->last_beacon = jiffies; 1577 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
1578 mod_beacon_timer(sdata);
1524 1579
1525 list_del(&wk->list); 1580 list_del(&wk->list);
1526 kfree(wk); 1581 kfree(wk);
@@ -1604,11 +1659,22 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1604 1659
1605 if (ifmgd->associated && 1660 if (ifmgd->associated &&
1606 memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && 1661 memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 &&
1607 ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { 1662 ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
1608 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; 1663 IEEE80211_STA_CONNECTION_POLL)) {
1664 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
1665 IEEE80211_STA_BEACON_POLL);
1609 mutex_lock(&sdata->local->iflist_mtx); 1666 mutex_lock(&sdata->local->iflist_mtx);
1610 ieee80211_recalc_ps(sdata->local, -1); 1667 ieee80211_recalc_ps(sdata->local, -1);
1611 mutex_unlock(&sdata->local->iflist_mtx); 1668 mutex_unlock(&sdata->local->iflist_mtx);
1669 /*
1670 * We've received a probe response, but are not sure whether
1671 * we have or will be receiving any beacons or data, so let's
1672 * schedule the timers again, just in case.
1673 */
1674 mod_beacon_timer(sdata);
1675 mod_timer(&ifmgd->conn_mon_timer,
1676 round_jiffies_up(jiffies +
1677 IEEE80211_CONNECTION_IDLE_TIME));
1612 } 1678 }
1613} 1679}
1614 1680
@@ -1658,27 +1724,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1658 if (rx_status->freq != local->hw.conf.channel->center_freq) 1724 if (rx_status->freq != local->hw.conf.channel->center_freq)
1659 return; 1725 return;
1660 1726
1661 if (WARN_ON(!ifmgd->associated)) 1727 /*
1728 * We might have received a number of frames, among them a
1729 * disassoc frame and a beacon...
1730 */
1731 if (!ifmgd->associated)
1662 return; 1732 return;
1663 1733
1664 bssid = ifmgd->associated->cbss.bssid; 1734 bssid = ifmgd->associated->cbss.bssid;
1665 1735
1666 if (WARN_ON(memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)) 1736 /*
1737 * And in theory even frames from a different AP we were just
1738 * associated to a split-second ago!
1739 */
1740 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)
1667 return; 1741 return;
1668 1742
1669 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { 1743 if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) {
1670#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 1744#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1671 if (net_ratelimit()) { 1745 if (net_ratelimit()) {
1672 printk(KERN_DEBUG "%s: cancelling probereq poll due " 1746 printk(KERN_DEBUG "%s: cancelling probereq poll due "
1673 "to a received beacon\n", sdata->dev->name); 1747 "to a received beacon\n", sdata->dev->name);
1674 } 1748 }
1675#endif 1749#endif
1676 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; 1750 ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
1677 mutex_lock(&local->iflist_mtx); 1751 mutex_lock(&local->iflist_mtx);
1678 ieee80211_recalc_ps(local, -1); 1752 ieee80211_recalc_ps(local, -1);
1679 mutex_unlock(&local->iflist_mtx); 1753 mutex_unlock(&local->iflist_mtx);
1680 } 1754 }
1681 1755
1756 /*
1757 * Push the beacon loss detection into the future since
1758 * we are processing a beacon from the AP just now.
1759 */
1760 mod_beacon_timer(sdata);
1761
1682 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); 1762 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
1683 ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, 1763 ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
1684 len - baselen, &elems, 1764 len - baselen, &elems,
@@ -1980,6 +2060,37 @@ static void ieee80211_sta_work(struct work_struct *work)
1980 /* then process the rest of the work */ 2060 /* then process the rest of the work */
1981 mutex_lock(&ifmgd->mtx); 2061 mutex_lock(&ifmgd->mtx);
1982 2062
2063 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
2064 IEEE80211_STA_CONNECTION_POLL) &&
2065 ifmgd->associated) {
2066 if (time_is_after_jiffies(ifmgd->probe_timeout))
2067 run_again(ifmgd, ifmgd->probe_timeout);
2068 else {
2069 u8 bssid[ETH_ALEN];
2070 /*
2071 * We actually lost the connection ... or did we?
2072 * Let's make sure!
2073 */
2074 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
2075 IEEE80211_STA_BEACON_POLL);
2076 memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
2077 printk(KERN_DEBUG "No probe response from AP %pM"
2078 " after %dms, disconnecting.\n",
2079 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
2080 ieee80211_set_disassoc(sdata);
2081 mutex_unlock(&ifmgd->mtx);
2082 /*
2083 * must be outside lock due to cfg80211,
2084 * but that's not a problem.
2085 */
2086 ieee80211_send_deauth_disassoc(sdata, bssid,
2087 IEEE80211_STYPE_DEAUTH,
2088 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
2089 NULL);
2090 mutex_lock(&ifmgd->mtx);
2091 }
2092 }
2093
1983 list_for_each_entry(wk, &ifmgd->work_list, list) { 2094 list_for_each_entry(wk, &ifmgd->work_list, list) {
1984 if (wk->state != IEEE80211_MGD_STATE_IDLE) { 2095 if (wk->state != IEEE80211_MGD_STATE_IDLE) {
1985 anybusy = true; 2096 anybusy = true;
@@ -2067,15 +2178,51 @@ static void ieee80211_sta_work(struct work_struct *work)
2067 ieee80211_recalc_idle(local); 2178 ieee80211_recalc_idle(local);
2068} 2179}
2069 2180
2181static void ieee80211_sta_bcn_mon_timer(unsigned long data)
2182{
2183 struct ieee80211_sub_if_data *sdata =
2184 (struct ieee80211_sub_if_data *) data;
2185 struct ieee80211_local *local = sdata->local;
2186
2187 if (local->quiescing)
2188 return;
2189
2190 queue_work(sdata->local->hw.workqueue,
2191 &sdata->u.mgd.beacon_loss_work);
2192}
2193
2194static void ieee80211_sta_conn_mon_timer(unsigned long data)
2195{
2196 struct ieee80211_sub_if_data *sdata =
2197 (struct ieee80211_sub_if_data *) data;
2198 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2199 struct ieee80211_local *local = sdata->local;
2200
2201 if (local->quiescing)
2202 return;
2203
2204 queue_work(local->hw.workqueue, &ifmgd->monitor_work);
2205}
2206
2207static void ieee80211_sta_monitor_work(struct work_struct *work)
2208{
2209 struct ieee80211_sub_if_data *sdata =
2210 container_of(work, struct ieee80211_sub_if_data,
2211 u.mgd.monitor_work);
2212
2213 ieee80211_mgd_probe_ap(sdata, false);
2214}
2215
2070static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) 2216static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
2071{ 2217{
2072 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 2218 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
2073 /* 2219 sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL |
2074 * Need to update last_beacon to avoid beacon loss 2220 IEEE80211_STA_CONNECTION_POLL);
2075 * test to trigger.
2076 */
2077 sdata->u.mgd.last_beacon = jiffies;
2078 2221
2222 /* let's probe the connection once */
2223 queue_work(sdata->local->hw.workqueue,
2224 &sdata->u.mgd.monitor_work);
2225 /* and do all the other regular work too */
2079 queue_work(sdata->local->hw.workqueue, 2226 queue_work(sdata->local->hw.workqueue,
2080 &sdata->u.mgd.work); 2227 &sdata->u.mgd.work);
2081 } 2228 }
@@ -2100,6 +2247,11 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
2100 cancel_work_sync(&ifmgd->chswitch_work); 2247 cancel_work_sync(&ifmgd->chswitch_work);
2101 if (del_timer_sync(&ifmgd->chswitch_timer)) 2248 if (del_timer_sync(&ifmgd->chswitch_timer))
2102 set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); 2249 set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
2250
2251 cancel_work_sync(&ifmgd->monitor_work);
2252 /* these will just be re-established on connection */
2253 del_timer_sync(&ifmgd->conn_mon_timer);
2254 del_timer_sync(&ifmgd->bcn_mon_timer);
2103} 2255}
2104 2256
2105void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) 2257void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
@@ -2120,10 +2272,15 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2120 2272
2121 ifmgd = &sdata->u.mgd; 2273 ifmgd = &sdata->u.mgd;
2122 INIT_WORK(&ifmgd->work, ieee80211_sta_work); 2274 INIT_WORK(&ifmgd->work, ieee80211_sta_work);
2275 INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
2123 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); 2276 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
2124 INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); 2277 INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
2125 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 2278 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
2126 (unsigned long) sdata); 2279 (unsigned long) sdata);
2280 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
2281 (unsigned long) sdata);
2282 setup_timer(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer,
2283 (unsigned long) sdata);
2127 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, 2284 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
2128 (unsigned long) sdata); 2285 (unsigned long) sdata);
2129 skb_queue_head_init(&ifmgd->skb_queue); 2286 skb_queue_head_init(&ifmgd->skb_queue);
@@ -2323,7 +2480,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2323 2480
2324 if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { 2481 if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
2325 bssid = req->bss->bssid; 2482 bssid = req->bss->bssid;
2326 ieee80211_set_disassoc(sdata, bssid, true); 2483 ieee80211_set_disassoc(sdata);
2327 } else list_for_each_entry(wk, &ifmgd->work_list, list) { 2484 } else list_for_each_entry(wk, &ifmgd->work_list, list) {
2328 if (&wk->bss->cbss == req->bss) { 2485 if (&wk->bss->cbss == req->bss) {
2329 bssid = req->bss->bssid; 2486 bssid = req->bss->bssid;
@@ -2365,7 +2522,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2365 return -ENOLINK; 2522 return -ENOLINK;
2366 } 2523 }
2367 2524
2368 ieee80211_set_disassoc(sdata, req->bss->bssid, false); 2525 ieee80211_set_disassoc(sdata);
2369 2526
2370 mutex_unlock(&ifmgd->mtx); 2527 mutex_unlock(&ifmgd->mtx);
2371 2528
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index fe6b99059531..b513fb791153 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -833,28 +833,22 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
833 if (!sta) 833 if (!sta)
834 return RX_CONTINUE; 834 return RX_CONTINUE;
835 835
836 /* Update last_rx only for IBSS packets which are for the current 836 /*
837 * BSSID to avoid keeping the current IBSS network alive in cases where 837 * Update last_rx only for IBSS packets which are for the current
838 * other STAs are using different BSSID. */ 838 * BSSID to avoid keeping the current IBSS network alive in cases
839 * where other STAs start using different BSSID.
840 */
839 if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { 841 if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
840 u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, 842 u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
841 NL80211_IFTYPE_ADHOC); 843 NL80211_IFTYPE_ADHOC);
842 if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) 844 if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0)
843 sta->last_rx = jiffies; 845 sta->last_rx = jiffies;
844 } else 846 } else if (!is_multicast_ether_addr(hdr->addr1)) {
845 if (!is_multicast_ether_addr(hdr->addr1) || 847 /*
846 rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
847 /* Update last_rx only for unicast frames in order to prevent
848 * the Probe Request frames (the only broadcast frames from a
849 * STA in infrastructure mode) from keeping a connection alive.
850 * Mesh beacons will update last_rx when if they are found to 848 * Mesh beacons will update last_rx when if they are found to
851 * match the current local configuration when processed. 849 * match the current local configuration when processed.
852 */ 850 */
853 if (rx->sdata->vif.type == NL80211_IFTYPE_STATION && 851 sta->last_rx = jiffies;
854 ieee80211_is_beacon(hdr->frame_control)) {
855 rx->sdata->u.mgd.last_beacon = jiffies;
856 } else
857 sta->last_rx = jiffies;
858 } 852 }
859 853
860 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 854 if (!(rx->flags & IEEE80211_RX_RA_MATCH))