aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mlme.c92
-rw-r--r--net/mac80211/status.c4
3 files changed, 72 insertions, 26 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ff7bc307827b..5bc0745368fe 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1265,6 +1265,8 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
1265 int powersave); 1265 int powersave);
1266void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1266void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1267 struct ieee80211_hdr *hdr); 1267 struct ieee80211_hdr *hdr);
1268void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1269 struct ieee80211_hdr *hdr);
1268void ieee80211_beacon_connection_loss_work(struct work_struct *work); 1270void ieee80211_beacon_connection_loss_work(struct work_struct *work);
1269 1271
1270void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 1272void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 849d9c639add..33ffce3ec605 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1034,6 +1034,51 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1034 ieee80211_sta_reset_conn_monitor(sdata); 1034 ieee80211_sta_reset_conn_monitor(sdata);
1035} 1035}
1036 1036
1037static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
1038{
1039 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1040
1041 if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
1042 IEEE80211_STA_CONNECTION_POLL)))
1043 return;
1044
1045 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
1046 IEEE80211_STA_BEACON_POLL);
1047 mutex_lock(&sdata->local->iflist_mtx);
1048 ieee80211_recalc_ps(sdata->local, -1);
1049 mutex_unlock(&sdata->local->iflist_mtx);
1050
1051 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
1052 return;
1053
1054 /*
1055 * We've received a probe response, but are not sure whether
1056 * we have or will be receiving any beacons or data, so let's
1057 * schedule the timers again, just in case.
1058 */
1059 ieee80211_sta_reset_beacon_monitor(sdata);
1060
1061 mod_timer(&ifmgd->conn_mon_timer,
1062 round_jiffies_up(jiffies +
1063 IEEE80211_CONNECTION_IDLE_TIME));
1064}
1065
1066void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1067 struct ieee80211_hdr *hdr)
1068{
1069 if (!ieee80211_is_data(hdr->frame_control) &&
1070 !ieee80211_is_nullfunc(hdr->frame_control))
1071 return;
1072
1073 ieee80211_sta_reset_conn_monitor(sdata);
1074
1075 if (ieee80211_is_nullfunc(hdr->frame_control) &&
1076 sdata->u.mgd.probe_send_count > 0) {
1077 sdata->u.mgd.probe_send_count = 0;
1078 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
1079 }
1080}
1081
1037static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) 1082static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1038{ 1083{
1039 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1084 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -1049,8 +1094,19 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1049 if (ifmgd->probe_send_count >= unicast_limit) 1094 if (ifmgd->probe_send_count >= unicast_limit)
1050 dst = NULL; 1095 dst = NULL;
1051 1096
1052 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1097 /*
1053 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); 1098 * When the hardware reports an accurate Tx ACK status, it's
1099 * better to send a nullfunc frame instead of a probe request,
1100 * as it will kick us off the AP quickly if we aren't associated
1101 * anymore. The timeout will be reset if the frame is ACKed by
1102 * the AP.
1103 */
1104 if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
1105 ieee80211_send_nullfunc(sdata->local, sdata, 0);
1106 else {
1107 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1108 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
1109 }
1054 1110
1055 ifmgd->probe_send_count++; 1111 ifmgd->probe_send_count++;
1056 ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; 1112 ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
@@ -1517,29 +1573,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1517 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); 1573 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1518 1574
1519 if (ifmgd->associated && 1575 if (ifmgd->associated &&
1520 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && 1576 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0)
1521 ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 1577 ieee80211_reset_ap_probe(sdata);
1522 IEEE80211_STA_CONNECTION_POLL)) {
1523 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
1524 IEEE80211_STA_BEACON_POLL);
1525 mutex_lock(&sdata->local->iflist_mtx);
1526 ieee80211_recalc_ps(sdata->local, -1);
1527 mutex_unlock(&sdata->local->iflist_mtx);
1528
1529 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
1530 return;
1531
1532 /*
1533 * We've received a probe response, but are not sure whether
1534 * we have or will be receiving any beacons or data, so let's
1535 * schedule the timers again, just in case.
1536 */
1537 ieee80211_sta_reset_beacon_monitor(sdata);
1538
1539 mod_timer(&ifmgd->conn_mon_timer,
1540 round_jiffies_up(jiffies +
1541 IEEE80211_CONNECTION_IDLE_TIME));
1542 }
1543} 1578}
1544 1579
1545/* 1580/*
@@ -1891,7 +1926,12 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
1891 u8 bssid[ETH_ALEN]; 1926 u8 bssid[ETH_ALEN];
1892 1927
1893 memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); 1928 memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
1894 if (time_is_after_jiffies(ifmgd->probe_timeout)) 1929
1930 /* ACK received for nullfunc probing frame */
1931 if (!ifmgd->probe_send_count)
1932 ieee80211_reset_ap_probe(sdata);
1933
1934 else if (time_is_after_jiffies(ifmgd->probe_timeout))
1895 run_again(ifmgd, ifmgd->probe_timeout); 1935 run_again(ifmgd, ifmgd->probe_timeout);
1896 1936
1897 else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) { 1937 else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) {
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 3153c19893b8..8695cd11dfd9 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -155,6 +155,10 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
155 155
156 ieee80211_queue_work(&local->hw, &local->recalc_smps); 156 ieee80211_queue_work(&local->hw, &local->recalc_smps);
157 } 157 }
158
159 if ((sdata->vif.type == NL80211_IFTYPE_STATION) &&
160 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
161 ieee80211_sta_tx_notify(sdata, (void *) skb->data);
158} 162}
159 163
160void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) 164void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)