diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/agg-tx.c | 44 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 12 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 21 | ||||
-rw-r--r-- | net/mac80211/iface.c | 23 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/rx.c | 13 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 83 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/trace.h | 31 | ||||
-rw-r--r-- | net/mac80211/tx.c | 115 | ||||
-rw-r--r-- | net/mac80211/util.c | 22 |
11 files changed, 350 insertions, 19 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 20522492d8cc..cce9d425c718 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -188,6 +188,43 @@ ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) | |||
188 | __release(agg_queue); | 188 | __release(agg_queue); |
189 | } | 189 | } |
190 | 190 | ||
191 | static void | ||
192 | ieee80211_agg_stop_txq(struct sta_info *sta, int tid) | ||
193 | { | ||
194 | struct ieee80211_txq *txq = sta->sta.txq[tid]; | ||
195 | struct txq_info *txqi; | ||
196 | |||
197 | if (!txq) | ||
198 | return; | ||
199 | |||
200 | txqi = to_txq_info(txq); | ||
201 | |||
202 | /* Lock here to protect against further seqno updates on dequeue */ | ||
203 | spin_lock_bh(&txqi->queue.lock); | ||
204 | set_bit(IEEE80211_TXQ_STOP, &txqi->flags); | ||
205 | spin_unlock_bh(&txqi->queue.lock); | ||
206 | } | ||
207 | |||
208 | static void | ||
209 | ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable) | ||
210 | { | ||
211 | struct ieee80211_txq *txq = sta->sta.txq[tid]; | ||
212 | struct txq_info *txqi; | ||
213 | |||
214 | if (!txq) | ||
215 | return; | ||
216 | |||
217 | txqi = to_txq_info(txq); | ||
218 | |||
219 | if (enable) | ||
220 | set_bit(IEEE80211_TXQ_AMPDU, &txqi->flags); | ||
221 | else | ||
222 | clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags); | ||
223 | |||
224 | clear_bit(IEEE80211_TXQ_STOP, &txqi->flags); | ||
225 | drv_wake_tx_queue(sta->sdata->local, txqi); | ||
226 | } | ||
227 | |||
191 | /* | 228 | /* |
192 | * splice packets from the STA's pending to the local pending, | 229 | * splice packets from the STA's pending to the local pending, |
193 | * requires a call to ieee80211_agg_splice_finish later | 230 | * requires a call to ieee80211_agg_splice_finish later |
@@ -247,6 +284,7 @@ static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid) | |||
247 | ieee80211_assign_tid_tx(sta, tid, NULL); | 284 | ieee80211_assign_tid_tx(sta, tid, NULL); |
248 | 285 | ||
249 | ieee80211_agg_splice_finish(sta->sdata, tid); | 286 | ieee80211_agg_splice_finish(sta->sdata, tid); |
287 | ieee80211_agg_start_txq(sta, tid, false); | ||
250 | 288 | ||
251 | kfree_rcu(tid_tx, rcu_head); | 289 | kfree_rcu(tid_tx, rcu_head); |
252 | } | 290 | } |
@@ -418,6 +456,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
418 | */ | 456 | */ |
419 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | 457 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
420 | 458 | ||
459 | ieee80211_agg_stop_txq(sta, tid); | ||
460 | |||
421 | /* | 461 | /* |
422 | * Make sure no packets are being processed. This ensures that | 462 | * Make sure no packets are being processed. This ensures that |
423 | * we have a valid starting sequence number and that in-flight | 463 | * we have a valid starting sequence number and that in-flight |
@@ -440,6 +480,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
440 | ieee80211_agg_splice_finish(sdata, tid); | 480 | ieee80211_agg_splice_finish(sdata, tid); |
441 | spin_unlock_bh(&sta->lock); | 481 | spin_unlock_bh(&sta->lock); |
442 | 482 | ||
483 | ieee80211_agg_start_txq(sta, tid, false); | ||
484 | |||
443 | kfree_rcu(tid_tx, rcu_head); | 485 | kfree_rcu(tid_tx, rcu_head); |
444 | return; | 486 | return; |
445 | } | 487 | } |
@@ -669,6 +711,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
669 | ieee80211_agg_splice_finish(sta->sdata, tid); | 711 | ieee80211_agg_splice_finish(sta->sdata, tid); |
670 | 712 | ||
671 | spin_unlock_bh(&sta->lock); | 713 | spin_unlock_bh(&sta->lock); |
714 | |||
715 | ieee80211_agg_start_txq(sta, tid, true); | ||
672 | } | 716 | } |
673 | 717 | ||
674 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | 718 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 0a39d3db951a..26e1ca8a474a 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -1367,4 +1367,16 @@ drv_tdls_recv_channel_switch(struct ieee80211_local *local, | |||
1367 | trace_drv_return_void(local); | 1367 | trace_drv_return_void(local); |
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | static inline void drv_wake_tx_queue(struct ieee80211_local *local, | ||
1371 | struct txq_info *txq) | ||
1372 | { | ||
1373 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif); | ||
1374 | |||
1375 | if (!check_sdata_in_driver(sdata)) | ||
1376 | return; | ||
1377 | |||
1378 | trace_drv_wake_tx_queue(local, sdata, txq); | ||
1379 | local->ops->wake_tx_queue(&local->hw, &txq->txq); | ||
1380 | } | ||
1381 | |||
1370 | #endif /* __MAC80211_DRIVER_OPS */ | 1382 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3c1512b0442c..04b32f3e0395 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -811,6 +811,19 @@ struct mac80211_qos_map { | |||
811 | struct rcu_head rcu_head; | 811 | struct rcu_head rcu_head; |
812 | }; | 812 | }; |
813 | 813 | ||
814 | enum txq_info_flags { | ||
815 | IEEE80211_TXQ_STOP, | ||
816 | IEEE80211_TXQ_AMPDU, | ||
817 | }; | ||
818 | |||
819 | struct txq_info { | ||
820 | struct sk_buff_head queue; | ||
821 | unsigned long flags; | ||
822 | |||
823 | /* keep last! */ | ||
824 | struct ieee80211_txq txq; | ||
825 | }; | ||
826 | |||
814 | struct ieee80211_sub_if_data { | 827 | struct ieee80211_sub_if_data { |
815 | struct list_head list; | 828 | struct list_head list; |
816 | 829 | ||
@@ -853,6 +866,7 @@ struct ieee80211_sub_if_data { | |||
853 | bool control_port_no_encrypt; | 866 | bool control_port_no_encrypt; |
854 | int encrypt_headroom; | 867 | int encrypt_headroom; |
855 | 868 | ||
869 | atomic_t txqs_len[IEEE80211_NUM_ACS]; | ||
856 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; | 870 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; |
857 | struct mac80211_qos_map __rcu *qos_map; | 871 | struct mac80211_qos_map __rcu *qos_map; |
858 | 872 | ||
@@ -1450,6 +1464,10 @@ static inline struct ieee80211_local *hw_to_local( | |||
1450 | return container_of(hw, struct ieee80211_local, hw); | 1464 | return container_of(hw, struct ieee80211_local, hw); |
1451 | } | 1465 | } |
1452 | 1466 | ||
1467 | static inline struct txq_info *to_txq_info(struct ieee80211_txq *txq) | ||
1468 | { | ||
1469 | return container_of(txq, struct txq_info, txq); | ||
1470 | } | ||
1453 | 1471 | ||
1454 | static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | 1472 | static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) |
1455 | { | 1473 | { |
@@ -1906,6 +1924,9 @@ static inline bool ieee80211_can_run_worker(struct ieee80211_local *local) | |||
1906 | return true; | 1924 | return true; |
1907 | } | 1925 | } |
1908 | 1926 | ||
1927 | void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata, | ||
1928 | struct sta_info *sta, | ||
1929 | struct txq_info *txq, int tid); | ||
1909 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1930 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1910 | u16 transaction, u16 auth_alg, u16 status, | 1931 | u16 transaction, u16 auth_alg, u16 status, |
1911 | const u8 *extra, size_t extra_len, const u8 *bssid, | 1932 | const u8 *extra, size_t extra_len, const u8 *bssid, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a0cd97fd0c49..b4ac596a7cb7 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -969,6 +969,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
969 | } | 969 | } |
970 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 970 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
971 | 971 | ||
972 | if (sdata->vif.txq) { | ||
973 | struct txq_info *txqi = to_txq_info(sdata->vif.txq); | ||
974 | |||
975 | ieee80211_purge_tx_queue(&local->hw, &txqi->queue); | ||
976 | atomic_set(&sdata->txqs_len[txqi->txq.ac], 0); | ||
977 | } | ||
978 | |||
972 | if (local->open_count == 0) | 979 | if (local->open_count == 0) |
973 | ieee80211_clear_tx_pending(local); | 980 | ieee80211_clear_tx_pending(local); |
974 | 981 | ||
@@ -1654,6 +1661,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1654 | { | 1661 | { |
1655 | struct net_device *ndev = NULL; | 1662 | struct net_device *ndev = NULL; |
1656 | struct ieee80211_sub_if_data *sdata = NULL; | 1663 | struct ieee80211_sub_if_data *sdata = NULL; |
1664 | struct txq_info *txqi; | ||
1657 | int ret, i; | 1665 | int ret, i; |
1658 | int txqs = 1; | 1666 | int txqs = 1; |
1659 | 1667 | ||
@@ -1673,10 +1681,18 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1673 | ieee80211_assign_perm_addr(local, wdev->address, type); | 1681 | ieee80211_assign_perm_addr(local, wdev->address, type); |
1674 | memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); | 1682 | memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); |
1675 | } else { | 1683 | } else { |
1684 | int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size, | ||
1685 | sizeof(void *)); | ||
1686 | int txq_size = 0; | ||
1687 | |||
1688 | if (local->ops->wake_tx_queue) | ||
1689 | txq_size += sizeof(struct txq_info) + | ||
1690 | local->hw.txq_data_size; | ||
1691 | |||
1676 | if (local->hw.queues >= IEEE80211_NUM_ACS) | 1692 | if (local->hw.queues >= IEEE80211_NUM_ACS) |
1677 | txqs = IEEE80211_NUM_ACS; | 1693 | txqs = IEEE80211_NUM_ACS; |
1678 | 1694 | ||
1679 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, | 1695 | ndev = alloc_netdev_mqs(size + txq_size, |
1680 | name, name_assign_type, | 1696 | name, name_assign_type, |
1681 | ieee80211_if_setup, txqs, 1); | 1697 | ieee80211_if_setup, txqs, 1); |
1682 | if (!ndev) | 1698 | if (!ndev) |
@@ -1711,6 +1727,11 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1711 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | 1727 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); |
1712 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | 1728 | memcpy(sdata->name, ndev->name, IFNAMSIZ); |
1713 | 1729 | ||
1730 | if (txq_size) { | ||
1731 | txqi = netdev_priv(ndev) + size; | ||
1732 | ieee80211_init_tx_queue(sdata, NULL, txqi, 0); | ||
1733 | } | ||
1734 | |||
1714 | sdata->dev = ndev; | 1735 | sdata->dev = ndev; |
1715 | } | 1736 | } |
1716 | 1737 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 51e0332a4589..df3051d96aff 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1039,6 +1039,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1039 | 1039 | ||
1040 | local->dynamic_ps_forced_timeout = -1; | 1040 | local->dynamic_ps_forced_timeout = -1; |
1041 | 1041 | ||
1042 | if (!local->hw.txq_ac_max_pending) | ||
1043 | local->hw.txq_ac_max_pending = 64; | ||
1044 | |||
1042 | result = ieee80211_wep_init(local); | 1045 | result = ieee80211_wep_init(local); |
1043 | if (result < 0) | 1046 | if (result < 0) |
1044 | wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", | 1047 | wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5b60bcf00ec3..bc59c8a20a39 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1184,6 +1184,7 @@ static void sta_ps_start(struct sta_info *sta) | |||
1184 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1184 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1185 | struct ieee80211_local *local = sdata->local; | 1185 | struct ieee80211_local *local = sdata->local; |
1186 | struct ps_data *ps; | 1186 | struct ps_data *ps; |
1187 | int tid; | ||
1187 | 1188 | ||
1188 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || | 1189 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
1189 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1190 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -1197,6 +1198,18 @@ static void sta_ps_start(struct sta_info *sta) | |||
1197 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); | 1198 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); |
1198 | ps_dbg(sdata, "STA %pM aid %d enters power save mode\n", | 1199 | ps_dbg(sdata, "STA %pM aid %d enters power save mode\n", |
1199 | sta->sta.addr, sta->sta.aid); | 1200 | sta->sta.addr, sta->sta.aid); |
1201 | |||
1202 | if (!sta->sta.txq[0]) | ||
1203 | return; | ||
1204 | |||
1205 | for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { | ||
1206 | struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); | ||
1207 | |||
1208 | if (!skb_queue_len(&txqi->queue)) | ||
1209 | set_bit(tid, &sta->txq_buffered_tids); | ||
1210 | else | ||
1211 | clear_bit(tid, &sta->txq_buffered_tids); | ||
1212 | } | ||
1200 | } | 1213 | } |
1201 | 1214 | ||
1202 | static void sta_ps_end(struct sta_info *sta) | 1215 | static void sta_ps_end(struct sta_info *sta) |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 81cc499fa4a9..12971b71d0fa 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -106,6 +106,16 @@ static void __cleanup_single_sta(struct sta_info *sta) | |||
106 | atomic_dec(&ps->num_sta_ps); | 106 | atomic_dec(&ps->num_sta_ps); |
107 | } | 107 | } |
108 | 108 | ||
109 | if (sta->sta.txq[0]) { | ||
110 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { | ||
111 | struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); | ||
112 | int n = skb_queue_len(&txqi->queue); | ||
113 | |||
114 | ieee80211_purge_tx_queue(&local->hw, &txqi->queue); | ||
115 | atomic_sub(n, &sdata->txqs_len[txqi->txq.ac]); | ||
116 | } | ||
117 | } | ||
118 | |||
109 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 119 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
110 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); | 120 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); |
111 | ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); | 121 | ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); |
@@ -218,6 +228,8 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) | |||
218 | 228 | ||
219 | sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); | 229 | sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); |
220 | 230 | ||
231 | if (sta->sta.txq[0]) | ||
232 | kfree(to_txq_info(sta->sta.txq[0])); | ||
221 | kfree(rcu_dereference_raw(sta->sta.rates)); | 233 | kfree(rcu_dereference_raw(sta->sta.rates)); |
222 | kfree(sta); | 234 | kfree(sta); |
223 | } | 235 | } |
@@ -268,11 +280,12 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
268 | const u8 *addr, gfp_t gfp) | 280 | const u8 *addr, gfp_t gfp) |
269 | { | 281 | { |
270 | struct ieee80211_local *local = sdata->local; | 282 | struct ieee80211_local *local = sdata->local; |
283 | struct ieee80211_hw *hw = &local->hw; | ||
271 | struct sta_info *sta; | 284 | struct sta_info *sta; |
272 | struct timespec uptime; | 285 | struct timespec uptime; |
273 | int i; | 286 | int i; |
274 | 287 | ||
275 | sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); | 288 | sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp); |
276 | if (!sta) | 289 | if (!sta) |
277 | return NULL; | 290 | return NULL; |
278 | 291 | ||
@@ -304,11 +317,25 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
304 | for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) | 317 | for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) |
305 | ewma_init(&sta->chain_signal_avg[i], 1024, 8); | 318 | ewma_init(&sta->chain_signal_avg[i], 1024, 8); |
306 | 319 | ||
307 | if (sta_prepare_rate_control(local, sta, gfp)) { | 320 | if (local->ops->wake_tx_queue) { |
308 | kfree(sta); | 321 | void *txq_data; |
309 | return NULL; | 322 | int size = sizeof(struct txq_info) + |
323 | ALIGN(hw->txq_data_size, sizeof(void *)); | ||
324 | |||
325 | txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp); | ||
326 | if (!txq_data) | ||
327 | goto free; | ||
328 | |||
329 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { | ||
330 | struct txq_info *txq = txq_data + i * size; | ||
331 | |||
332 | ieee80211_init_tx_queue(sdata, sta, txq, i); | ||
333 | } | ||
310 | } | 334 | } |
311 | 335 | ||
336 | if (sta_prepare_rate_control(local, sta, gfp)) | ||
337 | goto free_txq; | ||
338 | |||
312 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | 339 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
313 | /* | 340 | /* |
314 | * timer_to_tid must be initialized with identity mapping | 341 | * timer_to_tid must be initialized with identity mapping |
@@ -329,7 +356,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
329 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 356 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
330 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { | 357 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { |
331 | struct ieee80211_supported_band *sband = | 358 | struct ieee80211_supported_band *sband = |
332 | local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; | 359 | hw->wiphy->bands[ieee80211_get_sdata_band(sdata)]; |
333 | u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> | 360 | u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> |
334 | IEEE80211_HT_CAP_SM_PS_SHIFT; | 361 | IEEE80211_HT_CAP_SM_PS_SHIFT; |
335 | /* | 362 | /* |
@@ -354,6 +381,13 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
354 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); | 381 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); |
355 | 382 | ||
356 | return sta; | 383 | return sta; |
384 | |||
385 | free_txq: | ||
386 | if (sta->sta.txq[0]) | ||
387 | kfree(to_txq_info(sta->sta.txq[0])); | ||
388 | free: | ||
389 | kfree(sta); | ||
390 | return NULL; | ||
357 | } | 391 | } |
358 | 392 | ||
359 | static int sta_info_insert_check(struct sta_info *sta) | 393 | static int sta_info_insert_check(struct sta_info *sta) |
@@ -623,6 +657,8 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending) | |||
623 | 657 | ||
624 | indicate_tim |= | 658 | indicate_tim |= |
625 | sta->driver_buffered_tids & tids; | 659 | sta->driver_buffered_tids & tids; |
660 | indicate_tim |= | ||
661 | sta->txq_buffered_tids & tids; | ||
626 | } | 662 | } |
627 | 663 | ||
628 | done: | 664 | done: |
@@ -1072,7 +1108,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1072 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1108 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1073 | struct ieee80211_local *local = sdata->local; | 1109 | struct ieee80211_local *local = sdata->local; |
1074 | struct sk_buff_head pending; | 1110 | struct sk_buff_head pending; |
1075 | int filtered = 0, buffered = 0, ac; | 1111 | int filtered = 0, buffered = 0, ac, i; |
1076 | unsigned long flags; | 1112 | unsigned long flags; |
1077 | struct ps_data *ps; | 1113 | struct ps_data *ps; |
1078 | 1114 | ||
@@ -1091,10 +1127,22 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1091 | 1127 | ||
1092 | BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); | 1128 | BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); |
1093 | sta->driver_buffered_tids = 0; | 1129 | sta->driver_buffered_tids = 0; |
1130 | sta->txq_buffered_tids = 0; | ||
1094 | 1131 | ||
1095 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) | 1132 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
1096 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); | 1133 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); |
1097 | 1134 | ||
1135 | if (sta->sta.txq[0]) { | ||
1136 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { | ||
1137 | struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); | ||
1138 | |||
1139 | if (!skb_queue_len(&txqi->queue)) | ||
1140 | continue; | ||
1141 | |||
1142 | drv_wake_tx_queue(local, txqi); | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1098 | skb_queue_head_init(&pending); | 1146 | skb_queue_head_init(&pending); |
1099 | 1147 | ||
1100 | /* sync with ieee80211_tx_h_unicast_ps_buf */ | 1148 | /* sync with ieee80211_tx_h_unicast_ps_buf */ |
@@ -1276,8 +1324,10 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1276 | /* if we already have frames from software, then we can't also | 1324 | /* if we already have frames from software, then we can't also |
1277 | * release from hardware queues | 1325 | * release from hardware queues |
1278 | */ | 1326 | */ |
1279 | if (skb_queue_empty(&frames)) | 1327 | if (skb_queue_empty(&frames)) { |
1280 | driver_release_tids |= sta->driver_buffered_tids & tids; | 1328 | driver_release_tids |= sta->driver_buffered_tids & tids; |
1329 | driver_release_tids |= sta->txq_buffered_tids & tids; | ||
1330 | } | ||
1281 | 1331 | ||
1282 | if (driver_release_tids) { | 1332 | if (driver_release_tids) { |
1283 | /* If the driver has data on more than one TID then | 1333 | /* If the driver has data on more than one TID then |
@@ -1448,6 +1498,9 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1448 | 1498 | ||
1449 | sta_info_recalc_tim(sta); | 1499 | sta_info_recalc_tim(sta); |
1450 | } else { | 1500 | } else { |
1501 | unsigned long tids = sta->txq_buffered_tids & driver_release_tids; | ||
1502 | int tid; | ||
1503 | |||
1451 | /* | 1504 | /* |
1452 | * We need to release a frame that is buffered somewhere in the | 1505 | * We need to release a frame that is buffered somewhere in the |
1453 | * driver ... it'll have to handle that. | 1506 | * driver ... it'll have to handle that. |
@@ -1467,8 +1520,22 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1467 | * that the TID(s) became empty before returning here from the | 1520 | * that the TID(s) became empty before returning here from the |
1468 | * release function. | 1521 | * release function. |
1469 | * Either way, however, when the driver tells us that the TID(s) | 1522 | * Either way, however, when the driver tells us that the TID(s) |
1470 | * became empty we'll do the TIM recalculation. | 1523 | * became empty or we find that a txq became empty, we'll do the |
1524 | * TIM recalculation. | ||
1471 | */ | 1525 | */ |
1526 | |||
1527 | if (!sta->sta.txq[0]) | ||
1528 | return; | ||
1529 | |||
1530 | for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { | ||
1531 | struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); | ||
1532 | |||
1533 | if (!(tids & BIT(tid)) || skb_queue_len(&txqi->queue)) | ||
1534 | continue; | ||
1535 | |||
1536 | sta_info_recalc_tim(sta); | ||
1537 | break; | ||
1538 | } | ||
1472 | } | 1539 | } |
1473 | } | 1540 | } |
1474 | 1541 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 97f25b9e52be..691d8a1f94a5 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -275,6 +275,7 @@ struct sta_ampdu_mlme { | |||
275 | * entered power saving state, these are also delivered to | 275 | * entered power saving state, these are also delivered to |
276 | * the station when it leaves powersave or polls for frames | 276 | * the station when it leaves powersave or polls for frames |
277 | * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on | 277 | * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on |
278 | * @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on | ||
278 | * @rx_packets: Number of MSDUs received from this STA | 279 | * @rx_packets: Number of MSDUs received from this STA |
279 | * @rx_bytes: Number of bytes received from this STA | 280 | * @rx_bytes: Number of bytes received from this STA |
280 | * @last_rx: time (in jiffies) when last frame was received from this STA | 281 | * @last_rx: time (in jiffies) when last frame was received from this STA |
@@ -369,6 +370,7 @@ struct sta_info { | |||
369 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; | 370 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; |
370 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; | 371 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; |
371 | unsigned long driver_buffered_tids; | 372 | unsigned long driver_buffered_tids; |
373 | unsigned long txq_buffered_tids; | ||
372 | 374 | ||
373 | /* Updated from RX path only, no locking requirements */ | 375 | /* Updated from RX path only, no locking requirements */ |
374 | unsigned long rx_packets; | 376 | unsigned long rx_packets; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index e9e462b349e5..790bd45081c4 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -2312,6 +2312,37 @@ TRACE_EVENT(drv_tdls_recv_channel_switch, | |||
2312 | ) | 2312 | ) |
2313 | ); | 2313 | ); |
2314 | 2314 | ||
2315 | TRACE_EVENT(drv_wake_tx_queue, | ||
2316 | TP_PROTO(struct ieee80211_local *local, | ||
2317 | struct ieee80211_sub_if_data *sdata, | ||
2318 | struct txq_info *txq), | ||
2319 | |||
2320 | TP_ARGS(local, sdata, txq), | ||
2321 | |||
2322 | TP_STRUCT__entry( | ||
2323 | LOCAL_ENTRY | ||
2324 | VIF_ENTRY | ||
2325 | STA_ENTRY | ||
2326 | __field(u8, ac) | ||
2327 | __field(u8, tid) | ||
2328 | ), | ||
2329 | |||
2330 | TP_fast_assign( | ||
2331 | struct ieee80211_sta *sta = txq->txq.sta; | ||
2332 | |||
2333 | LOCAL_ASSIGN; | ||
2334 | VIF_ASSIGN; | ||
2335 | STA_ASSIGN; | ||
2336 | __entry->ac = txq->txq.ac; | ||
2337 | __entry->tid = txq->txq.tid; | ||
2338 | ), | ||
2339 | |||
2340 | TP_printk( | ||
2341 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ac:%d tid:%d", | ||
2342 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ac, __entry->tid | ||
2343 | ) | ||
2344 | ); | ||
2345 | |||
2315 | #ifdef CONFIG_MAC80211_MESSAGE_TRACING | 2346 | #ifdef CONFIG_MAC80211_MESSAGE_TRACING |
2316 | #undef TRACE_SYSTEM | 2347 | #undef TRACE_SYSTEM |
2317 | #define TRACE_SYSTEM mac80211_msg | 2348 | #define TRACE_SYSTEM mac80211_msg |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9f7fb4eec37b..667111ee6a20 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -767,12 +767,22 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
767 | return TX_CONTINUE; | 767 | return TX_CONTINUE; |
768 | } | 768 | } |
769 | 769 | ||
770 | static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid) | ||
771 | { | ||
772 | u16 *seq = &sta->tid_seq[tid]; | ||
773 | __le16 ret = cpu_to_le16(*seq); | ||
774 | |||
775 | /* Increase the sequence number. */ | ||
776 | *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; | ||
777 | |||
778 | return ret; | ||
779 | } | ||
780 | |||
770 | static ieee80211_tx_result debug_noinline | 781 | static ieee80211_tx_result debug_noinline |
771 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | 782 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) |
772 | { | 783 | { |
773 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 784 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
774 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 785 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
775 | u16 *seq; | ||
776 | u8 *qc; | 786 | u8 *qc; |
777 | int tid; | 787 | int tid; |
778 | 788 | ||
@@ -823,13 +833,10 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
823 | 833 | ||
824 | qc = ieee80211_get_qos_ctl(hdr); | 834 | qc = ieee80211_get_qos_ctl(hdr); |
825 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 835 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
826 | seq = &tx->sta->tid_seq[tid]; | ||
827 | tx->sta->tx_msdu[tid]++; | 836 | tx->sta->tx_msdu[tid]++; |
828 | 837 | ||
829 | hdr->seq_ctrl = cpu_to_le16(*seq); | 838 | if (!tx->sta->sta.txq[0]) |
830 | 839 | hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid); | |
831 | /* Increase the sequence number. */ | ||
832 | *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; | ||
833 | 840 | ||
834 | return TX_CONTINUE; | 841 | return TX_CONTINUE; |
835 | } | 842 | } |
@@ -1070,7 +1077,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1070 | * nothing -- this aggregation session is being started | 1077 | * nothing -- this aggregation session is being started |
1071 | * but that might still fail with the driver | 1078 | * but that might still fail with the driver |
1072 | */ | 1079 | */ |
1073 | } else { | 1080 | } else if (!tx->sta->sta.txq[tid]) { |
1074 | spin_lock(&tx->sta->lock); | 1081 | spin_lock(&tx->sta->lock); |
1075 | /* | 1082 | /* |
1076 | * Need to re-check now, because we may get here | 1083 | * Need to re-check now, because we may get here |
@@ -1211,13 +1218,102 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1211 | return TX_CONTINUE; | 1218 | return TX_CONTINUE; |
1212 | } | 1219 | } |
1213 | 1220 | ||
1221 | static void ieee80211_drv_tx(struct ieee80211_local *local, | ||
1222 | struct ieee80211_vif *vif, | ||
1223 | struct ieee80211_sta *pubsta, | ||
1224 | struct sk_buff *skb) | ||
1225 | { | ||
1226 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1227 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1228 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1229 | struct ieee80211_tx_control control = { | ||
1230 | .sta = pubsta, | ||
1231 | }; | ||
1232 | struct ieee80211_txq *txq = NULL; | ||
1233 | struct txq_info *txqi; | ||
1234 | u8 ac; | ||
1235 | |||
1236 | if (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE) | ||
1237 | goto tx_normal; | ||
1238 | |||
1239 | if (!ieee80211_is_data(hdr->frame_control)) | ||
1240 | goto tx_normal; | ||
1241 | |||
1242 | if (pubsta) { | ||
1243 | u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; | ||
1244 | |||
1245 | txq = pubsta->txq[tid]; | ||
1246 | } else if (vif) { | ||
1247 | txq = vif->txq; | ||
1248 | } | ||
1249 | |||
1250 | if (!txq) | ||
1251 | goto tx_normal; | ||
1252 | |||
1253 | ac = txq->ac; | ||
1254 | txqi = to_txq_info(txq); | ||
1255 | atomic_inc(&sdata->txqs_len[ac]); | ||
1256 | if (atomic_read(&sdata->txqs_len[ac]) >= local->hw.txq_ac_max_pending) | ||
1257 | netif_stop_subqueue(sdata->dev, ac); | ||
1258 | |||
1259 | skb_queue_tail(&txqi->queue, skb); | ||
1260 | drv_wake_tx_queue(local, txqi); | ||
1261 | |||
1262 | return; | ||
1263 | |||
1264 | tx_normal: | ||
1265 | drv_tx(local, &control, skb); | ||
1266 | } | ||
1267 | |||
1268 | struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, | ||
1269 | struct ieee80211_txq *txq) | ||
1270 | { | ||
1271 | struct ieee80211_local *local = hw_to_local(hw); | ||
1272 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif); | ||
1273 | struct txq_info *txqi = container_of(txq, struct txq_info, txq); | ||
1274 | struct ieee80211_hdr *hdr; | ||
1275 | struct sk_buff *skb = NULL; | ||
1276 | u8 ac = txq->ac; | ||
1277 | |||
1278 | spin_lock_bh(&txqi->queue.lock); | ||
1279 | |||
1280 | if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags)) | ||
1281 | goto out; | ||
1282 | |||
1283 | skb = __skb_dequeue(&txqi->queue); | ||
1284 | if (!skb) | ||
1285 | goto out; | ||
1286 | |||
1287 | atomic_dec(&sdata->txqs_len[ac]); | ||
1288 | if (__netif_subqueue_stopped(sdata->dev, ac)) | ||
1289 | ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]); | ||
1290 | |||
1291 | hdr = (struct ieee80211_hdr *)skb->data; | ||
1292 | if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) { | ||
1293 | struct sta_info *sta = container_of(txq->sta, struct sta_info, | ||
1294 | sta); | ||
1295 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1296 | |||
1297 | hdr->seq_ctrl = ieee80211_tx_next_seq(sta, txq->tid); | ||
1298 | if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags)) | ||
1299 | info->flags |= IEEE80211_TX_CTL_AMPDU; | ||
1300 | else | ||
1301 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
1302 | } | ||
1303 | |||
1304 | out: | ||
1305 | spin_unlock_bh(&txqi->queue.lock); | ||
1306 | |||
1307 | return skb; | ||
1308 | } | ||
1309 | EXPORT_SYMBOL(ieee80211_tx_dequeue); | ||
1310 | |||
1214 | static bool ieee80211_tx_frags(struct ieee80211_local *local, | 1311 | static bool ieee80211_tx_frags(struct ieee80211_local *local, |
1215 | struct ieee80211_vif *vif, | 1312 | struct ieee80211_vif *vif, |
1216 | struct ieee80211_sta *sta, | 1313 | struct ieee80211_sta *sta, |
1217 | struct sk_buff_head *skbs, | 1314 | struct sk_buff_head *skbs, |
1218 | bool txpending) | 1315 | bool txpending) |
1219 | { | 1316 | { |
1220 | struct ieee80211_tx_control control; | ||
1221 | struct sk_buff *skb, *tmp; | 1317 | struct sk_buff *skb, *tmp; |
1222 | unsigned long flags; | 1318 | unsigned long flags; |
1223 | 1319 | ||
@@ -1275,10 +1371,9 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1275 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 1371 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
1276 | 1372 | ||
1277 | info->control.vif = vif; | 1373 | info->control.vif = vif; |
1278 | control.sta = sta; | ||
1279 | 1374 | ||
1280 | __skb_unlink(skb, skbs); | 1375 | __skb_unlink(skb, skbs); |
1281 | drv_tx(local, &control, skb); | 1376 | ieee80211_drv_tx(local, vif, sta, skb); |
1282 | } | 1377 | } |
1283 | 1378 | ||
1284 | return true; | 1379 | return true; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d1742a7d9ea4..482b85c19a36 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -308,6 +308,11 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | |||
308 | for (ac = 0; ac < n_acs; ac++) { | 308 | for (ac = 0; ac < n_acs; ac++) { |
309 | int ac_queue = sdata->vif.hw_queue[ac]; | 309 | int ac_queue = sdata->vif.hw_queue[ac]; |
310 | 310 | ||
311 | if (local->ops->wake_tx_queue && | ||
312 | (atomic_read(&sdata->txqs_len[ac]) > | ||
313 | local->hw.txq_ac_max_pending)) | ||
314 | continue; | ||
315 | |||
311 | if (ac_queue == queue || | 316 | if (ac_queue == queue || |
312 | (sdata->vif.cab_queue == queue && | 317 | (sdata->vif.cab_queue == queue && |
313 | local->queue_stop_reasons[ac_queue] == 0 && | 318 | local->queue_stop_reasons[ac_queue] == 0 && |
@@ -3352,3 +3357,20 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo) | |||
3352 | 3357 | ||
3353 | return buf; | 3358 | return buf; |
3354 | } | 3359 | } |
3360 | |||
3361 | void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata, | ||
3362 | struct sta_info *sta, | ||
3363 | struct txq_info *txqi, int tid) | ||
3364 | { | ||
3365 | skb_queue_head_init(&txqi->queue); | ||
3366 | txqi->txq.vif = &sdata->vif; | ||
3367 | |||
3368 | if (sta) { | ||
3369 | txqi->txq.sta = &sta->sta; | ||
3370 | sta->sta.txq[tid] = &txqi->txq; | ||
3371 | txqi->txq.ac = ieee802_1d_to_ac[tid & 7]; | ||
3372 | } else { | ||
3373 | sdata->vif.txq = &txqi->txq; | ||
3374 | txqi->txq.ac = IEEE80211_AC_BE; | ||
3375 | } | ||
3376 | } | ||