summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-01-29 13:13:50 +0100
committerJohannes Berg <johannes.berg@intel.com>2013-02-04 16:09:58 +0100
commit682bd38b8ac1fa3e84e84cddd1f1d7eeebce1212 (patch)
treeb05470db358c1a0b86552e5f659a098fc2968bfa /net
parenteef9e54ce8b8dd08e281e0c399cced807c98959e (diff)
downloadlinux-682bd38b8ac1fa3e84e84cddd1f1d7eeebce1212.tar.gz
linux-682bd38b8ac1fa3e84e84cddd1f1d7eeebce1212.tar.bz2
linux-682bd38b8ac1fa3e84e84cddd1f1d7eeebce1212.zip
mac80211: always allow calling ieee80211_connection_loss()
With multi-channel, there's a corner case where a driver doesn't receive a beacon soon enough to be able to sync its timers with the AP. In this case, the only recovery (after trying again) is to disconnect from the AP. Allow calling ieee80211_connection_loss() for such cases. To make that possible, modify the work function to not rely on the IEEE80211_HW_CONNECTION_MONITOR flag but use new state kept in the interface instead. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c6
2 files changed, 5 insertions, 2 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c9c66dec170a..25a0647ada8f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -391,6 +391,7 @@ struct ieee80211_if_managed {
unsigned long probe_timeout;
int probe_send_count;
bool nullfunc_failed;
+ bool connection_loss;
struct mutex mtx;
struct cfg80211_bss *associated;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 756df39f1aba..5e188a5d812f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1872,7 +1872,7 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
rcu_read_unlock();
}
- if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) {
+ if (ifmgd->connection_loss) {
sdata_info(sdata, "Connection to AP %pM lost\n",
ifmgd->bssid);
__ieee80211_disconnect(sdata);
@@ -1900,6 +1900,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
trace_api_beacon_loss(sdata);
WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR);
+ sdata->u.mgd.connection_loss = false;
ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
}
EXPORT_SYMBOL(ieee80211_beacon_loss);
@@ -1911,7 +1912,7 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif)
trace_api_connection_loss(sdata);
- WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR));
+ sdata->u.mgd.connection_loss = true;
ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
}
EXPORT_SYMBOL(ieee80211_connection_loss);
@@ -3154,6 +3155,7 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
if (local->quiescing)
return;
+ sdata->u.mgd.connection_loss = false;
ieee80211_queue_work(&sdata->local->hw,
&sdata->u.mgd.beacon_connection_loss_work);
}