summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mlme.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 898e9b02aaac..d779c57a8220 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -651,7 +651,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
}
if (count == 1 && found->u.mgd.powersave &&
- (found->u.mgd.flags & IEEE80211_STA_ASSOCIATED)) {
+ (found->u.mgd.flags & IEEE80211_STA_ASSOCIATED) &&
+ !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) {
s32 beaconint_us;
if (latency < 0)
@@ -1320,6 +1321,11 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
#endif
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
+
+ mutex_lock(&sdata->local->iflist_mtx);
+ ieee80211_recalc_ps(sdata->local, -1);
+ mutex_unlock(&sdata->local->iflist_mtx);
+
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
ifmgd->ssid_len, NULL, 0);
@@ -1340,6 +1346,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
+ unsigned long last_rx;
bool disassoc = false;
/* TODO: start monitoring current AP signal quality and number of
@@ -1356,17 +1363,21 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
sdata->dev->name, ifmgd->bssid);
disassoc = true;
- goto unlock;
+ rcu_read_unlock();
+ goto out;
}
+ last_rx = sta->last_rx;
+ rcu_read_unlock();
+
if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) &&
- time_after(jiffies, sta->last_rx + IEEE80211_PROBE_WAIT)) {
+ time_after(jiffies, last_rx + IEEE80211_PROBE_WAIT)) {
printk(KERN_DEBUG "%s: no probe response from AP %pM "
"- disassociating\n",
sdata->dev->name, ifmgd->bssid);
disassoc = true;
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
- goto unlock;
+ goto out;
}
/*
@@ -1385,26 +1396,29 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
}
#endif
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
+ mutex_lock(&local->iflist_mtx);
+ ieee80211_recalc_ps(local, -1);
+ mutex_unlock(&local->iflist_mtx);
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
ifmgd->ssid_len, NULL, 0);
mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
- goto unlock;
+ goto out;
}
- if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) {
+ if (time_after(jiffies, last_rx + IEEE80211_PROBE_IDLE_TIME)) {
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
+ mutex_lock(&local->iflist_mtx);
+ ieee80211_recalc_ps(local, -1);
+ mutex_unlock(&local->iflist_mtx);
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
ifmgd->ssid_len, NULL, 0);
}
+ out:
if (!disassoc)
mod_timer(&ifmgd->timer,
jiffies + IEEE80211_MONITORING_INTERVAL);
-
- unlock:
- rcu_read_unlock();
-
- if (disassoc)
+ else
ieee80211_set_disassoc(sdata, true, true,
WLAN_REASON_PREV_AUTH_NOT_VALID);
}
@@ -1887,8 +1901,12 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_authenticate(sdata);
}
- if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
+ if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
+ mutex_lock(&sdata->local->iflist_mtx);
+ ieee80211_recalc_ps(sdata->local, -1);
+ mutex_unlock(&sdata->local->iflist_mtx);
+ }
}
/*
@@ -1946,6 +1964,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
#endif
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
+ mutex_lock(&local->iflist_mtx);
+ ieee80211_recalc_ps(local, -1);
+ mutex_unlock(&local->iflist_mtx);
}
ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);