diff options
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 93 | ||||
-rw-r--r-- | net/mac80211/status.c | 18 |
3 files changed, 79 insertions, 35 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 66b0b52b828d..e7c880725639 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -357,6 +357,7 @@ struct ieee80211_if_managed { | |||
357 | unsigned long beacon_timeout; | 357 | unsigned long beacon_timeout; |
358 | unsigned long probe_timeout; | 358 | unsigned long probe_timeout; |
359 | int probe_send_count; | 359 | int probe_send_count; |
360 | bool nullfunc_failed; | ||
360 | 361 | ||
361 | struct mutex mtx; | 362 | struct mutex mtx; |
362 | struct cfg80211_bss *associated; | 363 | struct cfg80211_bss *associated; |
@@ -1271,7 +1272,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
1271 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1272 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1272 | struct ieee80211_hdr *hdr); | 1273 | struct ieee80211_hdr *hdr); |
1273 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | 1274 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, |
1274 | struct ieee80211_hdr *hdr); | 1275 | struct ieee80211_hdr *hdr, bool ack); |
1275 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); | 1276 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); |
1276 | 1277 | ||
1277 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1278 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f570801514f1..3a1dde3c7956 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1065,16 +1065,20 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) | |||
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | 1067 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, |
1068 | struct ieee80211_hdr *hdr) | 1068 | struct ieee80211_hdr *hdr, bool ack) |
1069 | { | 1069 | { |
1070 | if (!ieee80211_is_data(hdr->frame_control)) | 1070 | if (!ieee80211_is_data(hdr->frame_control)) |
1071 | return; | 1071 | return; |
1072 | 1072 | ||
1073 | ieee80211_sta_reset_conn_monitor(sdata); | 1073 | if (ack) |
1074 | ieee80211_sta_reset_conn_monitor(sdata); | ||
1074 | 1075 | ||
1075 | if (ieee80211_is_nullfunc(hdr->frame_control) && | 1076 | if (ieee80211_is_nullfunc(hdr->frame_control) && |
1076 | sdata->u.mgd.probe_send_count > 0) { | 1077 | sdata->u.mgd.probe_send_count > 0) { |
1077 | sdata->u.mgd.probe_send_count = 0; | 1078 | if (ack) |
1079 | sdata->u.mgd.probe_send_count = 0; | ||
1080 | else | ||
1081 | sdata->u.mgd.nullfunc_failed = true; | ||
1078 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 1082 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
1079 | } | 1083 | } |
1080 | } | 1084 | } |
@@ -1101,9 +1105,10 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1101 | * anymore. The timeout will be reset if the frame is ACKed by | 1105 | * anymore. The timeout will be reset if the frame is ACKed by |
1102 | * the AP. | 1106 | * the AP. |
1103 | */ | 1107 | */ |
1104 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 1108 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { |
1109 | ifmgd->nullfunc_failed = false; | ||
1105 | ieee80211_send_nullfunc(sdata->local, sdata, 0); | 1110 | ieee80211_send_nullfunc(sdata->local, sdata, 0); |
1106 | else { | 1111 | } else { |
1107 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1112 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1108 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); | 1113 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); |
1109 | } | 1114 | } |
@@ -1912,6 +1917,31 @@ static void ieee80211_sta_timer(unsigned long data) | |||
1912 | ieee80211_queue_work(&local->hw, &sdata->work); | 1917 | ieee80211_queue_work(&local->hw, &sdata->work); |
1913 | } | 1918 | } |
1914 | 1919 | ||
1920 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | ||
1921 | u8 *bssid) | ||
1922 | { | ||
1923 | struct ieee80211_local *local = sdata->local; | ||
1924 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1925 | |||
1926 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1927 | IEEE80211_STA_BEACON_POLL); | ||
1928 | |||
1929 | ieee80211_set_disassoc(sdata, true, true); | ||
1930 | mutex_unlock(&ifmgd->mtx); | ||
1931 | mutex_lock(&local->mtx); | ||
1932 | ieee80211_recalc_idle(local); | ||
1933 | mutex_unlock(&local->mtx); | ||
1934 | /* | ||
1935 | * must be outside lock due to cfg80211, | ||
1936 | * but that's not a problem. | ||
1937 | */ | ||
1938 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
1939 | IEEE80211_STYPE_DEAUTH, | ||
1940 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
1941 | NULL, true); | ||
1942 | mutex_lock(&ifmgd->mtx); | ||
1943 | } | ||
1944 | |||
1915 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | 1945 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) |
1916 | { | 1946 | { |
1917 | struct ieee80211_local *local = sdata->local; | 1947 | struct ieee80211_local *local = sdata->local; |
@@ -1936,11 +1966,38 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1936 | /* ACK received for nullfunc probing frame */ | 1966 | /* ACK received for nullfunc probing frame */ |
1937 | if (!ifmgd->probe_send_count) | 1967 | if (!ifmgd->probe_send_count) |
1938 | ieee80211_reset_ap_probe(sdata); | 1968 | ieee80211_reset_ap_probe(sdata); |
1939 | 1969 | else if (ifmgd->nullfunc_failed) { | |
1940 | else if (time_is_after_jiffies(ifmgd->probe_timeout)) | 1970 | if (ifmgd->probe_send_count < max_tries) { |
1971 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1972 | wiphy_debug(local->hw.wiphy, | ||
1973 | "%s: No ack for nullfunc frame to" | ||
1974 | " AP %pM, try %d\n", | ||
1975 | sdata->name, bssid, | ||
1976 | ifmgd->probe_send_count); | ||
1977 | #endif | ||
1978 | ieee80211_mgd_probe_ap_send(sdata); | ||
1979 | } else { | ||
1980 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1981 | wiphy_debug(local->hw.wiphy, | ||
1982 | "%s: No ack for nullfunc frame to" | ||
1983 | " AP %pM, disconnecting.\n", | ||
1984 | sdata->name, bssid, | ||
1985 | ifmgd->probe_send_count); | ||
1986 | #endif | ||
1987 | ieee80211_sta_connection_lost(sdata, bssid); | ||
1988 | } | ||
1989 | } else if (time_is_after_jiffies(ifmgd->probe_timeout)) | ||
1941 | run_again(ifmgd, ifmgd->probe_timeout); | 1990 | run_again(ifmgd, ifmgd->probe_timeout); |
1942 | 1991 | else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | |
1943 | else if (ifmgd->probe_send_count < max_tries) { | 1992 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1993 | wiphy_debug(local->hw.wiphy, | ||
1994 | "%s: Failed to send nullfunc to AP %pM" | ||
1995 | " after %dms, disconnecting.\n", | ||
1996 | sdata->name, | ||
1997 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | ||
1998 | #endif | ||
1999 | ieee80211_sta_connection_lost(sdata, bssid); | ||
2000 | } else if (ifmgd->probe_send_count < max_tries) { | ||
1944 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2001 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1945 | wiphy_debug(local->hw.wiphy, | 2002 | wiphy_debug(local->hw.wiphy, |
1946 | "%s: No probe response from AP %pM" | 2003 | "%s: No probe response from AP %pM" |
@@ -1955,27 +2012,13 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1955 | * We actually lost the connection ... or did we? | 2012 | * We actually lost the connection ... or did we? |
1956 | * Let's make sure! | 2013 | * Let's make sure! |
1957 | */ | 2014 | */ |
1958 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1959 | IEEE80211_STA_BEACON_POLL); | ||
1960 | wiphy_debug(local->hw.wiphy, | 2015 | wiphy_debug(local->hw.wiphy, |
1961 | "%s: No probe response from AP %pM" | 2016 | "%s: No probe response from AP %pM" |
1962 | " after %dms, disconnecting.\n", | 2017 | " after %dms, disconnecting.\n", |
1963 | sdata->name, | 2018 | sdata->name, |
1964 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2019 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1965 | ieee80211_set_disassoc(sdata, true, true); | 2020 | |
1966 | mutex_unlock(&ifmgd->mtx); | 2021 | ieee80211_sta_connection_lost(sdata, bssid); |
1967 | mutex_lock(&local->mtx); | ||
1968 | ieee80211_recalc_idle(local); | ||
1969 | mutex_unlock(&local->mtx); | ||
1970 | /* | ||
1971 | * must be outside lock due to cfg80211, | ||
1972 | * but that's not a problem. | ||
1973 | */ | ||
1974 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
1975 | IEEE80211_STYPE_DEAUTH, | ||
1976 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
1977 | NULL, true); | ||
1978 | mutex_lock(&ifmgd->mtx); | ||
1979 | } | 2022 | } |
1980 | } | 2023 | } |
1981 | 2024 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 4958710a7d92..38a797217a91 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -155,10 +155,6 @@ 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); | ||
162 | } | 158 | } |
163 | 159 | ||
164 | /* | 160 | /* |
@@ -186,6 +182,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
186 | int retry_count = -1, i; | 182 | int retry_count = -1, i; |
187 | int rates_idx = -1; | 183 | int rates_idx = -1; |
188 | bool send_to_cooked; | 184 | bool send_to_cooked; |
185 | bool acked; | ||
189 | 186 | ||
190 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 187 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
191 | /* the HW cannot have attempted that rate */ | 188 | /* the HW cannot have attempted that rate */ |
@@ -211,8 +208,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
211 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | 208 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) |
212 | continue; | 209 | continue; |
213 | 210 | ||
214 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | 211 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); |
215 | test_sta_flags(sta, WLAN_STA_PS_STA)) { | 212 | if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { |
216 | /* | 213 | /* |
217 | * The STA is in power save mode, so assume | 214 | * The STA is in power save mode, so assume |
218 | * that this TX packet failed because of that. | 215 | * that this TX packet failed because of that. |
@@ -244,7 +241,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
244 | rcu_read_unlock(); | 241 | rcu_read_unlock(); |
245 | return; | 242 | return; |
246 | } else { | 243 | } else { |
247 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) | 244 | if (!acked) |
248 | sta->tx_retry_failed++; | 245 | sta->tx_retry_failed++; |
249 | sta->tx_retry_count += retry_count; | 246 | sta->tx_retry_count += retry_count; |
250 | } | 247 | } |
@@ -253,10 +250,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
253 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | 250 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
254 | ieee80211s_update_metric(local, sta, skb); | 251 | ieee80211s_update_metric(local, sta, skb); |
255 | 252 | ||
256 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && | 253 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked) |
257 | (info->flags & IEEE80211_TX_STAT_ACK)) | ||
258 | ieee80211_frame_acked(sta, skb); | 254 | ieee80211_frame_acked(sta, skb); |
259 | 255 | ||
256 | if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) && | ||
257 | (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) | ||
258 | ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, acked); | ||
259 | |||
260 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | 260 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { |
261 | if (info->flags & IEEE80211_TX_STAT_ACK) { | 261 | if (info->flags & IEEE80211_TX_STAT_ACK) { |
262 | if (sta->lost_packets) | 262 | if (sta->lost_packets) |