|
@@ -610,6 +610,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
|
|
|
bss_info_changed |= ieee80211_handle_bss_capability(sdata,
|
|
|
bss->cbss.capability, bss->has_erp_value, bss->erp_value);
|
|
|
|
|
|
+ cfg80211_hold_bss(&bss->cbss);
|
|
|
+
|
|
|
ieee80211_rx_bss_put(local, bss);
|
|
|
}
|
|
|
|
|
@@ -751,6 +753,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
|
|
{
|
|
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
+ struct ieee80211_conf *conf = &local_to_hw(local)->conf;
|
|
|
+ struct ieee80211_bss *bss;
|
|
|
struct sta_info *sta;
|
|
|
u32 changed = 0, config_changed = 0;
|
|
|
|
|
@@ -774,6 +778,15 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
ieee80211_sta_tear_down_BA_sessions(sta);
|
|
|
|
|
|
+ bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
|
|
|
+ conf->channel->center_freq,
|
|
|
+ ifmgd->ssid, ifmgd->ssid_len);
|
|
|
+
|
|
|
+ if (bss) {
|
|
|
+ cfg80211_unhold_bss(&bss->cbss);
|
|
|
+ ieee80211_rx_bss_put(local, bss);
|
|
|
+ }
|
|
|
+
|
|
|
if (self_disconnected) {
|
|
|
if (deauth)
|
|
|
ieee80211_send_deauth_disassoc(sdata,
|
|
@@ -925,6 +938,33 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
|
|
|
jiffies + IEEE80211_MONITORING_INTERVAL);
|
|
|
}
|
|
|
|
|
|
+void ieee80211_beacon_loss_work(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct ieee80211_sub_if_data *sdata =
|
|
|
+ container_of(work, struct ieee80211_sub_if_data,
|
|
|
+ u.mgd.beacon_loss_work);
|
|
|
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
|
+
|
|
|
+ printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
|
|
|
+ "- sending probe request\n", sdata->dev->name,
|
|
|
+ sdata->u.mgd.bssid);
|
|
|
+
|
|
|
+ ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
|
|
|
+ ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
|
|
|
+ ifmgd->ssid_len, NULL, 0);
|
|
|
+
|
|
|
+ mod_timer(&ifmgd->timer, jiffies + IEEE80211_MONITORING_INTERVAL);
|
|
|
+}
|
|
|
+
|
|
|
+void ieee80211_beacon_loss(struct ieee80211_vif *vif)
|
|
|
+{
|
|
|
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
|
|
+
|
|
|
+ queue_work(sdata->local->hw.workqueue,
|
|
|
+ &sdata->u.mgd.beacon_loss_work);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(ieee80211_beacon_loss);
|
|
|
+
|
|
|
static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
|
|
|
{
|
|
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
@@ -959,7 +999,13 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
|
|
|
goto unlock;
|
|
|
}
|
|
|
|
|
|
- if (time_after(jiffies,
|
|
|
+ /*
|
|
|
+ * Beacon filtering is only enabled with power save and then the
|
|
|
+ * stack should not check for beacon loss.
|
|
|
+ */
|
|
|
+ if (!((local->hw.flags & IEEE80211_HW_BEACON_FILTER) &&
|
|
|
+ (local->hw.conf.flags & IEEE80211_CONF_PS)) &&
|
|
|
+ time_after(jiffies,
|
|
|
ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
|
|
|
printk(KERN_DEBUG "%s: beacon loss from AP %pM "
|
|
|
"- sending probe request\n",
|
|
@@ -1869,6 +1915,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
|
|
|
ifmgd = &sdata->u.mgd;
|
|
|
INIT_WORK(&ifmgd->work, ieee80211_sta_work);
|
|
|
INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
|
|
|
+ INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
|
|
|
setup_timer(&ifmgd->timer, ieee80211_sta_timer,
|
|
|
(unsigned long) sdata);
|
|
|
setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
|