summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-tx.c6
-rw-r--r--net/mac80211/driver-ops.h12
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/sta_info.c7
-rw-r--r--net/mac80211/trace.h32
-rw-r--r--net/mac80211/tx.c49
7 files changed, 73 insertions, 41 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 595c662a61e8..6c6cad98ce92 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -226,9 +226,13 @@ ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
226 clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags); 226 clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
227 227
228 clear_bit(IEEE80211_TXQ_STOP, &txqi->flags); 228 clear_bit(IEEE80211_TXQ_STOP, &txqi->flags);
229
230 if (!ieee80211_schedule_txq(&sta->sdata->local->hw, txq))
231 return;
232
229 local_bh_disable(); 233 local_bh_disable();
230 rcu_read_lock(); 234 rcu_read_lock();
231 drv_wake_tx_queue(sta->sdata->local, txqi); 235 drv_wake_tx_queue(sta->sdata->local);
232 rcu_read_unlock(); 236 rcu_read_unlock();
233 local_bh_enable(); 237 local_bh_enable();
234} 238}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index c7f93fd9ca7a..cdd76306cb8f 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1158,16 +1158,10 @@ drv_tdls_recv_channel_switch(struct ieee80211_local *local,
1158 trace_drv_return_void(local); 1158 trace_drv_return_void(local);
1159} 1159}
1160 1160
1161static inline void drv_wake_tx_queue(struct ieee80211_local *local, 1161static inline void drv_wake_tx_queue(struct ieee80211_local *local)
1162 struct txq_info *txq)
1163{ 1162{
1164 struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif); 1163 trace_drv_wake_tx_queue(local);
1165 1164 local->ops->wake_tx_queue(&local->hw);
1166 if (!check_sdata_in_driver(sdata))
1167 return;
1168
1169 trace_drv_wake_tx_queue(local, sdata, txq);
1170 local->ops->wake_tx_queue(&local->hw, &txq->txq);
1171} 1165}
1172 1166
1173static inline int drv_start_nan(struct ieee80211_local *local, 1167static inline int drv_start_nan(struct ieee80211_local *local,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 26900025de2f..4155838c7bef 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -832,6 +832,7 @@ struct txq_info {
832 struct codel_vars def_cvars; 832 struct codel_vars def_cvars;
833 struct codel_stats cstats; 833 struct codel_stats cstats;
834 struct sk_buff_head frags; 834 struct sk_buff_head frags;
835 struct list_head schedule_order;
835 unsigned long flags; 836 unsigned long flags;
836 837
837 /* keep last! */ 838 /* keep last! */
@@ -1122,6 +1123,10 @@ struct ieee80211_local {
1122 struct codel_vars *cvars; 1123 struct codel_vars *cvars;
1123 struct codel_params cparams; 1124 struct codel_params cparams;
1124 1125
1126 /* protects active_txqs and txqi->schedule_order */
1127 spinlock_t active_txq_lock;
1128 struct list_head active_txqs;
1129
1125 const struct ieee80211_ops *ops; 1130 const struct ieee80211_ops *ops;
1126 1131
1127 /* 1132 /*
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0785d04a80bc..935d6e2491b1 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -619,6 +619,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
619 spin_lock_init(&local->rx_path_lock); 619 spin_lock_init(&local->rx_path_lock);
620 spin_lock_init(&local->queue_stop_reason_lock); 620 spin_lock_init(&local->queue_stop_reason_lock);
621 621
622 INIT_LIST_HEAD(&local->active_txqs);
623 spin_lock_init(&local->active_txq_lock);
624
622 INIT_LIST_HEAD(&local->chanctx_list); 625 INIT_LIST_HEAD(&local->chanctx_list);
623 mutex_init(&local->chanctx_mtx); 626 mutex_init(&local->chanctx_mtx);
624 627
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 0c5627f8a104..e0bcf16df494 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1237,12 +1237,17 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
1237 drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); 1237 drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
1238 1238
1239 if (sta->sta.txq[0]) { 1239 if (sta->sta.txq[0]) {
1240 bool wake = false;
1241
1240 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { 1242 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
1241 if (!txq_has_queue(sta->sta.txq[i])) 1243 if (!txq_has_queue(sta->sta.txq[i]))
1242 continue; 1244 continue;
1243 1245
1244 drv_wake_tx_queue(local, to_txq_info(sta->sta.txq[i])); 1246 if (ieee80211_schedule_txq(&local->hw, sta->sta.txq[i]))
1247 wake = true;
1245 } 1248 }
1249 if (wake)
1250 drv_wake_tx_queue(local);
1246 } 1251 }
1247 1252
1248 skb_queue_head_init(&pending); 1253 skb_queue_head_init(&pending);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 591ad02e1fa4..08eaad85942e 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2550,35 +2550,9 @@ TRACE_EVENT(drv_tdls_recv_channel_switch,
2550 ) 2550 )
2551); 2551);
2552 2552
2553TRACE_EVENT(drv_wake_tx_queue, 2553DEFINE_EVENT(local_only_evt, drv_wake_tx_queue,
2554 TP_PROTO(struct ieee80211_local *local, 2554 TP_PROTO(struct ieee80211_local *local),
2555 struct ieee80211_sub_if_data *sdata, 2555 TP_ARGS(local)
2556 struct txq_info *txq),
2557
2558 TP_ARGS(local, sdata, txq),
2559
2560 TP_STRUCT__entry(
2561 LOCAL_ENTRY
2562 VIF_ENTRY
2563 STA_ENTRY
2564 __field(u8, ac)
2565 __field(u8, tid)
2566 ),
2567
2568 TP_fast_assign(
2569 struct ieee80211_sta *sta = txq->txq.sta;
2570
2571 LOCAL_ASSIGN;
2572 VIF_ASSIGN;
2573 STA_ASSIGN;
2574 __entry->ac = txq->txq.ac;
2575 __entry->tid = txq->txq.tid;
2576 ),
2577
2578 TP_printk(
2579 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ac:%d tid:%d",
2580 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ac, __entry->tid
2581 )
2582); 2556);
2583 2557
2584#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ 2558#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 25904af38839..842881ca8f20 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1439,6 +1439,7 @@ void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
1439 codel_vars_init(&txqi->def_cvars); 1439 codel_vars_init(&txqi->def_cvars);
1440 codel_stats_init(&txqi->cstats); 1440 codel_stats_init(&txqi->cstats);
1441 __skb_queue_head_init(&txqi->frags); 1441 __skb_queue_head_init(&txqi->frags);
1442 INIT_LIST_HEAD(&txqi->schedule_order);
1442 1443
1443 txqi->txq.vif = &sdata->vif; 1444 txqi->txq.vif = &sdata->vif;
1444 1445
@@ -1462,6 +1463,7 @@ void ieee80211_txq_purge(struct ieee80211_local *local,
1462 1463
1463 fq_tin_reset(fq, tin, fq_skb_free_func); 1464 fq_tin_reset(fq, tin, fq_skb_free_func);
1464 ieee80211_purge_tx_queue(&local->hw, &txqi->frags); 1465 ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
1466 list_del_init(&txqi->schedule_order);
1465} 1467}
1466 1468
1467int ieee80211_txq_setup_flows(struct ieee80211_local *local) 1469int ieee80211_txq_setup_flows(struct ieee80211_local *local)
@@ -1558,7 +1560,8 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
1558 ieee80211_txq_enqueue(local, txqi, skb); 1560 ieee80211_txq_enqueue(local, txqi, skb);
1559 spin_unlock_bh(&fq->lock); 1561 spin_unlock_bh(&fq->lock);
1560 1562
1561 drv_wake_tx_queue(local, txqi); 1563 if (ieee80211_schedule_txq(&local->hw, &txqi->txq))
1564 drv_wake_tx_queue(local);
1562 1565
1563 return true; 1566 return true;
1564} 1567}
@@ -3553,6 +3556,50 @@ out:
3553} 3556}
3554EXPORT_SYMBOL(ieee80211_tx_dequeue); 3557EXPORT_SYMBOL(ieee80211_tx_dequeue);
3555 3558
3559bool ieee80211_schedule_txq(struct ieee80211_hw *hw,
3560 struct ieee80211_txq *txq)
3561{
3562 struct ieee80211_local *local = hw_to_local(hw);
3563 struct txq_info *txqi = to_txq_info(txq);
3564 bool ret = false;
3565
3566 spin_lock_bh(&local->active_txq_lock);
3567
3568 if (list_empty(&txqi->schedule_order)) {
3569 list_add_tail(&txqi->schedule_order, &local->active_txqs);
3570 ret = true;
3571 }
3572
3573 spin_unlock_bh(&local->active_txq_lock);
3574
3575 return ret;
3576}
3577EXPORT_SYMBOL(ieee80211_schedule_txq);
3578
3579struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw)
3580{
3581 struct ieee80211_local *local = hw_to_local(hw);
3582 struct txq_info *txqi = NULL;
3583
3584 spin_lock_bh(&local->active_txq_lock);
3585
3586 if (list_empty(&local->active_txqs))
3587 goto out;
3588
3589 txqi = list_first_entry(&local->active_txqs,
3590 struct txq_info, schedule_order);
3591 list_del_init(&txqi->schedule_order);
3592
3593out:
3594 spin_unlock_bh(&local->active_txq_lock);
3595
3596 if (!txqi)
3597 return NULL;
3598
3599 return &txqi->txq;
3600}
3601EXPORT_SYMBOL(ieee80211_next_txq);
3602
3556void __ieee80211_subif_start_xmit(struct sk_buff *skb, 3603void __ieee80211_subif_start_xmit(struct sk_buff *skb,
3557 struct net_device *dev, 3604 struct net_device *dev,
3558 u32 info_flags) 3605 u32 info_flags)