|
@@ -1065,16 +1065,20 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
|
|
}
|
|
}
|
|
|
|
|
|
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
|
|
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
|
|
- struct ieee80211_hdr *hdr)
|
|
|
|
|
|
+ struct ieee80211_hdr *hdr, bool ack)
|
|
{
|
|
{
|
|
if (!ieee80211_is_data(hdr->frame_control))
|
|
if (!ieee80211_is_data(hdr->frame_control))
|
|
return;
|
|
return;
|
|
|
|
|
|
- ieee80211_sta_reset_conn_monitor(sdata);
|
|
|
|
|
|
+ if (ack)
|
|
|
|
+ ieee80211_sta_reset_conn_monitor(sdata);
|
|
|
|
|
|
if (ieee80211_is_nullfunc(hdr->frame_control) &&
|
|
if (ieee80211_is_nullfunc(hdr->frame_control) &&
|
|
sdata->u.mgd.probe_send_count > 0) {
|
|
sdata->u.mgd.probe_send_count > 0) {
|
|
- sdata->u.mgd.probe_send_count = 0;
|
|
|
|
|
|
+ if (ack)
|
|
|
|
+ sdata->u.mgd.probe_send_count = 0;
|
|
|
|
+ else
|
|
|
|
+ sdata->u.mgd.nullfunc_failed = true;
|
|
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
|
|
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1101,9 +1105,10 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
|
|
* anymore. The timeout will be reset if the frame is ACKed by
|
|
* anymore. The timeout will be reset if the frame is ACKed by
|
|
* the AP.
|
|
* the AP.
|
|
*/
|
|
*/
|
|
- if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
|
|
|
|
|
|
+ if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
|
|
|
|
+ ifmgd->nullfunc_failed = false;
|
|
ieee80211_send_nullfunc(sdata->local, sdata, 0);
|
|
ieee80211_send_nullfunc(sdata->local, sdata, 0);
|
|
- else {
|
|
|
|
|
|
+ } else {
|
|
ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
|
|
ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
|
|
ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
|
|
ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
|
|
}
|
|
}
|
|
@@ -1912,6 +1917,31 @@ static void ieee80211_sta_timer(unsigned long data)
|
|
ieee80211_queue_work(&local->hw, &sdata->work);
|
|
ieee80211_queue_work(&local->hw, &sdata->work);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
|
|
|
|
+ u8 *bssid)
|
|
|
|
+{
|
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
|
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
|
|
+
|
|
|
|
+ ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
|
|
|
|
+ IEEE80211_STA_BEACON_POLL);
|
|
|
|
+
|
|
|
|
+ ieee80211_set_disassoc(sdata, true, true);
|
|
|
|
+ mutex_unlock(&ifmgd->mtx);
|
|
|
|
+ mutex_lock(&local->mtx);
|
|
|
|
+ ieee80211_recalc_idle(local);
|
|
|
|
+ mutex_unlock(&local->mtx);
|
|
|
|
+ /*
|
|
|
|
+ * must be outside lock due to cfg80211,
|
|
|
|
+ * but that's not a problem.
|
|
|
|
+ */
|
|
|
|
+ ieee80211_send_deauth_disassoc(sdata, bssid,
|
|
|
|
+ IEEE80211_STYPE_DEAUTH,
|
|
|
|
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
|
|
|
+ NULL, true);
|
|
|
|
+ mutex_lock(&ifmgd->mtx);
|
|
|
|
+}
|
|
|
|
+
|
|
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
|
|
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
|
|
{
|
|
{
|
|
struct ieee80211_local *local = sdata->local;
|
|
struct ieee80211_local *local = sdata->local;
|
|
@@ -1936,11 +1966,38 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
|
|
/* ACK received for nullfunc probing frame */
|
|
/* ACK received for nullfunc probing frame */
|
|
if (!ifmgd->probe_send_count)
|
|
if (!ifmgd->probe_send_count)
|
|
ieee80211_reset_ap_probe(sdata);
|
|
ieee80211_reset_ap_probe(sdata);
|
|
-
|
|
|
|
- else if (time_is_after_jiffies(ifmgd->probe_timeout))
|
|
|
|
|
|
+ else if (ifmgd->nullfunc_failed) {
|
|
|
|
+ if (ifmgd->probe_send_count < max_tries) {
|
|
|
|
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
|
|
+ wiphy_debug(local->hw.wiphy,
|
|
|
|
+ "%s: No ack for nullfunc frame to"
|
|
|
|
+ " AP %pM, try %d\n",
|
|
|
|
+ sdata->name, bssid,
|
|
|
|
+ ifmgd->probe_send_count);
|
|
|
|
+#endif
|
|
|
|
+ ieee80211_mgd_probe_ap_send(sdata);
|
|
|
|
+ } else {
|
|
|
|
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
|
|
+ wiphy_debug(local->hw.wiphy,
|
|
|
|
+ "%s: No ack for nullfunc frame to"
|
|
|
|
+ " AP %pM, disconnecting.\n",
|
|
|
|
+ sdata->name, bssid,
|
|
|
|
+ ifmgd->probe_send_count);
|
|
|
|
+#endif
|
|
|
|
+ ieee80211_sta_connection_lost(sdata, bssid);
|
|
|
|
+ }
|
|
|
|
+ } else if (time_is_after_jiffies(ifmgd->probe_timeout))
|
|
run_again(ifmgd, ifmgd->probe_timeout);
|
|
run_again(ifmgd, ifmgd->probe_timeout);
|
|
-
|
|
|
|
- else if (ifmgd->probe_send_count < max_tries) {
|
|
|
|
|
|
+ else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
|
|
|
|
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
|
|
+ wiphy_debug(local->hw.wiphy,
|
|
|
|
+ "%s: Failed to send nullfunc to AP %pM"
|
|
|
|
+ " after %dms, disconnecting.\n",
|
|
|
|
+ sdata->name,
|
|
|
|
+ bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
|
|
|
|
+#endif
|
|
|
|
+ ieee80211_sta_connection_lost(sdata, bssid);
|
|
|
|
+ } else if (ifmgd->probe_send_count < max_tries) {
|
|
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
wiphy_debug(local->hw.wiphy,
|
|
wiphy_debug(local->hw.wiphy,
|
|
"%s: No probe response from AP %pM"
|
|
"%s: No probe response from AP %pM"
|
|
@@ -1955,27 +2012,13 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
|
|
* We actually lost the connection ... or did we?
|
|
* We actually lost the connection ... or did we?
|
|
* Let's make sure!
|
|
* Let's make sure!
|
|
*/
|
|
*/
|
|
- ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
|
|
|
|
- IEEE80211_STA_BEACON_POLL);
|
|
|
|
wiphy_debug(local->hw.wiphy,
|
|
wiphy_debug(local->hw.wiphy,
|
|
"%s: No probe response from AP %pM"
|
|
"%s: No probe response from AP %pM"
|
|
" after %dms, disconnecting.\n",
|
|
" after %dms, disconnecting.\n",
|
|
sdata->name,
|
|
sdata->name,
|
|
bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
|
|
bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
|
|
- ieee80211_set_disassoc(sdata, true, true);
|
|
|
|
- mutex_unlock(&ifmgd->mtx);
|
|
|
|
- mutex_lock(&local->mtx);
|
|
|
|
- ieee80211_recalc_idle(local);
|
|
|
|
- mutex_unlock(&local->mtx);
|
|
|
|
- /*
|
|
|
|
- * must be outside lock due to cfg80211,
|
|
|
|
- * but that's not a problem.
|
|
|
|
- */
|
|
|
|
- ieee80211_send_deauth_disassoc(sdata, bssid,
|
|
|
|
- IEEE80211_STYPE_DEAUTH,
|
|
|
|
- WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
|
|
|
- NULL, true);
|
|
|
|
- mutex_lock(&ifmgd->mtx);
|
|
|
|
|
|
+
|
|
|
|
+ ieee80211_sta_connection_lost(sdata, bssid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|