diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-08-06 08:18:13 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-08-09 15:58:24 -0400 |
commit | f89d1bc4271153ac7864051778c0f2443e5cf2cd (patch) | |
tree | 6ffbdac8b042eb4cd6ceba24cbb891cfa1fd1ca6 /drivers/net/wireless/ath/ath9k | |
parent | 020f20f693c254a6daa727473d6e855a63c3e502 (diff) |
ath9k: use software queueing for multicast traffic
Create a per-vif dummy node entry for keeping the multicast software
queues. This helps in setups with a lot of mulitcast traffic that could
otherwise potentially drown out unicast traffic to stations.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 12 |
3 files changed, 23 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 41ea3fd5b9bb..505c615ada1b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -265,6 +265,7 @@ struct ath_node { | |||
265 | u8 mpdudensity; | 265 | u8 mpdudensity; |
266 | 266 | ||
267 | bool sleeping; | 267 | bool sleeping; |
268 | bool no_ps_filter; | ||
268 | 269 | ||
269 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) | 270 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) |
270 | struct dentry *node_stat; | 271 | struct dentry *node_stat; |
@@ -364,6 +365,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
364 | /********/ | 365 | /********/ |
365 | 366 | ||
366 | struct ath_vif { | 367 | struct ath_vif { |
368 | struct ath_node mcast_node; | ||
367 | int av_bslot; | 369 | int av_bslot; |
368 | bool primary_sta_vif; | 370 | bool primary_sta_vif; |
369 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ | 371 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 252497ae5089..911744f5c43c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -963,6 +963,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
963 | struct ath_softc *sc = hw->priv; | 963 | struct ath_softc *sc = hw->priv; |
964 | struct ath_hw *ah = sc->sc_ah; | 964 | struct ath_hw *ah = sc->sc_ah; |
965 | struct ath_common *common = ath9k_hw_common(ah); | 965 | struct ath_common *common = ath9k_hw_common(ah); |
966 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
967 | struct ath_node *an = &avp->mcast_node; | ||
966 | 968 | ||
967 | mutex_lock(&sc->mutex); | 969 | mutex_lock(&sc->mutex); |
968 | 970 | ||
@@ -976,6 +978,12 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
976 | if (ath9k_uses_beacons(vif->type)) | 978 | if (ath9k_uses_beacons(vif->type)) |
977 | ath9k_beacon_assign_slot(sc, vif); | 979 | ath9k_beacon_assign_slot(sc, vif); |
978 | 980 | ||
981 | an->sc = sc; | ||
982 | an->sta = NULL; | ||
983 | an->vif = vif; | ||
984 | an->no_ps_filter = true; | ||
985 | ath_tx_node_init(sc, an); | ||
986 | |||
979 | mutex_unlock(&sc->mutex); | 987 | mutex_unlock(&sc->mutex); |
980 | return 0; | 988 | return 0; |
981 | } | 989 | } |
@@ -1013,6 +1021,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1013 | { | 1021 | { |
1014 | struct ath_softc *sc = hw->priv; | 1022 | struct ath_softc *sc = hw->priv; |
1015 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1023 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1024 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
1016 | 1025 | ||
1017 | ath_dbg(common, CONFIG, "Detach Interface\n"); | 1026 | ath_dbg(common, CONFIG, "Detach Interface\n"); |
1018 | 1027 | ||
@@ -1027,6 +1036,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1027 | ath9k_calculate_summary_state(hw, NULL); | 1036 | ath9k_calculate_summary_state(hw, NULL); |
1028 | ath9k_ps_restore(sc); | 1037 | ath9k_ps_restore(sc); |
1029 | 1038 | ||
1039 | ath_tx_node_cleanup(sc, &avp->mcast_node); | ||
1040 | |||
1030 | mutex_unlock(&sc->mutex); | 1041 | mutex_unlock(&sc->mutex); |
1031 | } | 1042 | } |
1032 | 1043 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f9e6eb2a4e0b..d8dfb3ec818a 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -135,6 +135,9 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) | |||
135 | 135 | ||
136 | static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) | 136 | static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) |
137 | { | 137 | { |
138 | if (!tid->an->sta) | ||
139 | return; | ||
140 | |||
138 | ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, | 141 | ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, |
139 | seqno << IEEE80211_SEQ_SEQ_SHIFT); | 142 | seqno << IEEE80211_SEQ_SEQ_SHIFT); |
140 | } | 143 | } |
@@ -1382,7 +1385,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
1382 | if (list_empty(&bf_q)) | 1385 | if (list_empty(&bf_q)) |
1383 | return false; | 1386 | return false; |
1384 | 1387 | ||
1385 | if (tid->ac->clear_ps_filter) { | 1388 | if (tid->ac->clear_ps_filter || tid->an->no_ps_filter) { |
1386 | tid->ac->clear_ps_filter = false; | 1389 | tid->ac->clear_ps_filter = false; |
1387 | tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1390 | tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1388 | } | 1391 | } |
@@ -1572,7 +1575,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
1572 | sent++; | 1575 | sent++; |
1573 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); | 1576 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); |
1574 | 1577 | ||
1575 | if (!ath_tid_has_buffered(tid)) | 1578 | if (an->sta && !ath_tid_has_buffered(tid)) |
1576 | ieee80211_sta_set_buffered(an->sta, i, false); | 1579 | ieee80211_sta_set_buffered(an->sta, i, false); |
1577 | } | 1580 | } |
1578 | ath_txq_unlock_complete(sc, tid->ac->txq); | 1581 | ath_txq_unlock_complete(sc, tid->ac->txq); |
@@ -2104,6 +2107,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2104 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2107 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2105 | struct ieee80211_sta *sta = txctl->sta; | 2108 | struct ieee80211_sta *sta = txctl->sta; |
2106 | struct ieee80211_vif *vif = info->control.vif; | 2109 | struct ieee80211_vif *vif = info->control.vif; |
2110 | struct ath_vif *avp; | ||
2107 | struct ath_softc *sc = hw->priv; | 2111 | struct ath_softc *sc = hw->priv; |
2108 | int frmlen = skb->len + FCS_LEN; | 2112 | int frmlen = skb->len + FCS_LEN; |
2109 | int padpos, padsize; | 2113 | int padpos, padsize; |
@@ -2111,6 +2115,10 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2111 | /* NOTE: sta can be NULL according to net/mac80211.h */ | 2115 | /* NOTE: sta can be NULL according to net/mac80211.h */ |
2112 | if (sta) | 2116 | if (sta) |
2113 | txctl->an = (struct ath_node *)sta->drv_priv; | 2117 | txctl->an = (struct ath_node *)sta->drv_priv; |
2118 | else if (vif && ieee80211_is_data(hdr->frame_control)) { | ||
2119 | avp = (void *)vif->drv_priv; | ||
2120 | txctl->an = &avp->mcast_node; | ||
2121 | } | ||
2114 | 2122 | ||
2115 | if (info->control.hw_key) | 2123 | if (info->control.hw_key) |
2116 | frmlen += info->control.hw_key->icv_len; | 2124 | frmlen += info->control.hw_key->icv_len; |