diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 81 |
1 files changed, 53 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 704fcbcbe20..d6e54a3c88f 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -158,7 +158,6 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ath_frame_info *fi = get_frame_info(skb); - int hw_queue; int q = fi->txq; if (q < 0) @@ -168,10 +167,12 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, if (WARN_ON(--txq->pending_frames < 0)) txq->pending_frames = 0; - hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue; if (txq->stopped && txq->pending_frames < sc->tx.txq_max_pending[q]) { - ieee80211_wake_queue(sc->hw, hw_queue); + if (ath9k_is_chanctx_enabled()) + ieee80211_wake_queue(sc->hw, info->hw_queue); + else + ieee80211_wake_queue(sc->hw, q); txq->stopped = false; } } @@ -587,6 +588,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, memcpy(tx_info->control.rates, rates, sizeof(rates)); ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok); rc_update = false; + if (bf == bf->bf_lastbf) + ath_dynack_sample_tx_ts(sc->sc_ah, + bf->bf_mpdu, + ts); } ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, @@ -681,12 +686,15 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, if (bf_is_ampdu_not_probing(bf)) txq->axq_ampdu_depth--; + ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, + ts->ts_rateindex); if (!bf_isampdu(bf)) { if (!flush) { info = IEEE80211_SKB_CB(bf->bf_mpdu); memcpy(info->control.rates, bf->rates, sizeof(info->control.rates)); ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); + ath_dynack_sample_tx_ts(sc->sc_ah, bf->bf_mpdu, ts); } ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok); } else @@ -1836,15 +1844,17 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) if (txq->mac80211_qnum < 0) return; + if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) + return; + spin_lock_bh(&sc->chan_lock); ac_list = &sc->cur_chan->acq[txq->mac80211_qnum]; - spin_unlock_bh(&sc->chan_lock); - if (test_bit(ATH_OP_HW_RESET, &common->op_flags) || - list_empty(ac_list)) + if (list_empty(ac_list)) { + spin_unlock_bh(&sc->chan_lock); return; + } - spin_lock_bh(&sc->chan_lock); rcu_read_lock(); last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list); @@ -2132,6 +2142,28 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, return bf; } +void ath_assign_seq(struct ath_common *common, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct ath_vif *avp; + + if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) + return; + + if (!vif) + return; + + avp = (struct ath_vif *)vif->drv_priv; + + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + avp->seq_no += 0x10; + + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); +} + static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl) { @@ -2155,17 +2187,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, if (info->control.hw_key) frmlen += info->control.hw_key->icv_len; - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } + ath_assign_seq(ath9k_hw_common(sc->sc_ah), skb); if ((vif && vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_AP_VLAN) || @@ -2202,9 +2224,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_txq *txq = txctl->txq; struct ath_atx_tid *tid = NULL; struct ath_buf *bf; - bool queue; - int q, hw_queue; - int ret; + bool queue, skip_uapsd = false; + int q, ret; if (vif) avp = (void *)vif->drv_priv; @@ -2223,14 +2244,16 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, */ q = skb_get_queue_mapping(skb); - hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue; ath_txq_lock(sc, txq); if (txq == sc->tx.txq_map[q]) { fi->txq = q; if (++txq->pending_frames > sc->tx.txq_max_pending[q] && !txq->stopped) { - ieee80211_stop_queue(sc->hw, hw_queue); + if (ath9k_is_chanctx_enabled()) + ieee80211_stop_queue(sc->hw, info->hw_queue); + else + ieee80211_stop_queue(sc->hw, q); txq->stopped = true; } } @@ -2245,15 +2268,14 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, sc->cur_chan->stopped) && !txctl->force_channel) { if (!txctl->an) txctl->an = &avp->mcast_node; - info->flags &= ~IEEE80211_TX_CTL_PS_RESPONSE; queue = true; + skip_uapsd = true; } if (txctl->an && queue) tid = ath_get_skb_tid(sc, txctl->an, skb); - if (info->flags & (IEEE80211_TX_CTL_PS_RESPONSE | - IEEE80211_TX_CTL_TX_OFFCHAN)) { + if (!skip_uapsd && (info->flags & IEEE80211_TX_CTL_PS_RESPONSE)) { ath_txq_unlock(sc, txq); txq = sc->tx.uapsdq; ath_txq_lock(sc, txq); @@ -2632,8 +2654,11 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) sc->beacon.tx_processed = true; sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); - ath_chanctx_event(sc, NULL, - ATH_CHANCTX_EVENT_BEACON_SENT); + if (ath9k_is_chanctx_enabled()) { + ath_chanctx_event(sc, NULL, + ATH_CHANCTX_EVENT_BEACON_SENT); + } + ath9k_csa_update(sc); continue; } |