diff options
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 92 | ||||
-rw-r--r-- | net/mac80211/status.c | 4 |
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); |
1266 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1266 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1267 | struct ieee80211_hdr *hdr); | 1267 | struct ieee80211_hdr *hdr); |
1268 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | ||
1269 | struct ieee80211_hdr *hdr); | ||
1268 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); | 1270 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); |
1269 | 1271 | ||
1270 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1272 | void 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 | ||
1037 | static 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 | |||
1066 | void 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 | |||
1037 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | 1082 | static 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 | ||
160 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 164 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |