diff options
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r-- | net/mac80211/status.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index d78f36c64c7b..0c0850d37dda 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -134,6 +134,40 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
134 | dev_kfree_skb(skb); | 134 | dev_kfree_skb(skb); |
135 | } | 135 | } |
136 | 136 | ||
137 | static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | ||
138 | { | ||
139 | struct ieee80211_mgmt *mgmt = (void *) skb->data; | ||
140 | struct ieee80211_local *local = sta->local; | ||
141 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
142 | |||
143 | if (ieee80211_is_action(mgmt->frame_control) && | ||
144 | sdata->vif.type == NL80211_IFTYPE_STATION && | ||
145 | mgmt->u.action.category == WLAN_CATEGORY_HT && | ||
146 | mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) { | ||
147 | /* | ||
148 | * This update looks racy, but isn't -- if we come | ||
149 | * here we've definitely got a station that we're | ||
150 | * talking to, and on a managed interface that can | ||
151 | * only be the AP. And the only other place updating | ||
152 | * this variable is before we're associated. | ||
153 | */ | ||
154 | switch (mgmt->u.action.u.ht_smps.smps_control) { | ||
155 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: | ||
156 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
157 | break; | ||
158 | case WLAN_HT_SMPS_CONTROL_STATIC: | ||
159 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC; | ||
160 | break; | ||
161 | case WLAN_HT_SMPS_CONTROL_DISABLED: | ||
162 | default: /* shouldn't happen since we don't send that */ | ||
163 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF; | ||
164 | break; | ||
165 | } | ||
166 | |||
167 | ieee80211_queue_work(&local->hw, &local->recalc_smps); | ||
168 | } | ||
169 | } | ||
170 | |||
137 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 171 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |
138 | { | 172 | { |
139 | struct sk_buff *skb2; | 173 | struct sk_buff *skb2; |
@@ -146,7 +180,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
146 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 180 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
147 | struct ieee80211_sub_if_data *sdata; | 181 | struct ieee80211_sub_if_data *sdata; |
148 | struct net_device *prev_dev = NULL; | 182 | struct net_device *prev_dev = NULL; |
149 | struct sta_info *sta; | 183 | struct sta_info *sta, *tmp; |
150 | int retry_count = -1, i; | 184 | int retry_count = -1, i; |
151 | bool injected; | 185 | bool injected; |
152 | 186 | ||
@@ -166,9 +200,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
166 | 200 | ||
167 | sband = local->hw.wiphy->bands[info->band]; | 201 | sband = local->hw.wiphy->bands[info->band]; |
168 | 202 | ||
169 | sta = sta_info_get(local, hdr->addr1); | 203 | for_each_sta_info(local, hdr->addr1, sta, tmp) { |
204 | /* skip wrong virtual interface */ | ||
205 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | ||
206 | continue; | ||
170 | 207 | ||
171 | if (sta) { | ||
172 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | 208 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && |
173 | test_sta_flags(sta, WLAN_STA_PS_STA)) { | 209 | test_sta_flags(sta, WLAN_STA_PS_STA)) { |
174 | /* | 210 | /* |
@@ -208,6 +244,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
208 | rate_control_tx_status(local, sband, sta, skb); | 244 | rate_control_tx_status(local, sband, sta, skb); |
209 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | 245 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
210 | ieee80211s_update_metric(local, sta, skb); | 246 | ieee80211s_update_metric(local, sta, skb); |
247 | |||
248 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
249 | (info->flags & IEEE80211_TX_STAT_ACK)) | ||
250 | ieee80211_frame_acked(sta, skb); | ||
211 | } | 251 | } |
212 | 252 | ||
213 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |