]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/ath/ath9k/xmit.c
Merge remote-tracking branch 'wireless-next/master'
[karo-tx-linux.git] / drivers / net / wireless / ath / ath9k / xmit.c
index 5ac713d2ff5d22dc6d976291c6d97098bfbceafd..09cdbcd097394a3a2c324230c2743f5d181b0900 100644 (file)
@@ -1241,12 +1241,13 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
                if (bf->bf_next)
                        info.link = bf->bf_next->bf_daddr;
                else
-                       info.link = 0;
+                       info.link = (sc->tx99_state) ? bf->bf_daddr : 0;
 
                if (!bf_first) {
                        bf_first = bf;
 
-                       info.flags = ATH9K_TXDESC_INTREQ;
+                       if (!sc->tx99_state)
+                               info.flags = ATH9K_TXDESC_INTREQ;
                        if ((tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) ||
                            txq == sc->tx.uapsdq)
                                info.flags |= ATH9K_TXDESC_CLRDMASK;
@@ -1704,16 +1705,9 @@ int ath_cabq_update(struct ath_softc *sc)
        int qnum = sc->beacon.cabq->axq_qnum;
 
        ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
-       /*
-        * Ensure the readytime % is within the bounds.
-        */
-       if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
-               sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
-       else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
-               sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
 
        qi.tqi_readyTime = (cur_conf->beacon_interval *
-                           sc->config.cabqReadytime) / 100;
+                           ATH_CABQ_READY_TIME) / 100;
        ath_txq_update(sc, qnum, &qi);
 
        return 0;
@@ -1948,7 +1942,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
                        txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
        }
 
-       if (!edma) {
+       if (!edma || sc->tx99_state) {
                TX_STAT_INC(txq->axq_qnum, txstart);
                ath9k_hw_txstart(ah, txq->axq_qnum);
        }
@@ -1969,15 +1963,18 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
                               struct ath_atx_tid *tid, struct sk_buff *skb)
 {
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ath_frame_info *fi = get_frame_info(skb);
        struct list_head bf_head;
-       struct ath_buf *bf;
-
-       bf = fi->bf;
+       struct ath_buf *bf = fi->bf;
 
        INIT_LIST_HEAD(&bf_head);
        list_add_tail(&bf->list, &bf_head);
        bf->bf_state.bf_type = 0;
+       if (tid && (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
+               bf->bf_state.bf_type = BUF_AMPDU;
+               ath_tx_addto_baw(sc, tid, bf);
+       }
 
        bf->bf_next = NULL;
        bf->bf_lastbf = bf;
@@ -2024,6 +2021,9 @@ static void setup_frame_info(struct ieee80211_hw *hw,
                fi->keyix = ATH9K_TXKEYIX_INVALID;
        fi->keytype = keytype;
        fi->framelen = framelen;
+
+       if (!rate)
+               return;
        fi->rtscts_rate = rate->hw_value;
        if (short_preamble)
                fi->rtscts_rate |= rate->hw_value_short;
@@ -2034,8 +2034,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
        struct ath_hw *ah = sc->sc_ah;
        struct ath9k_channel *curchan = ah->curchan;
 
-       if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&
-           (curchan->channelFlags & CHANNEL_5GHZ) &&
+       if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && IS_CHAN_5GHZ(curchan) &&
            (chainmask == 0x7) && (rate < 0x90))
                return 0x3;
        else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) &&
@@ -2326,7 +2325,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
        ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
 
        if (sc->sc_ah->caldata)
-               sc->sc_ah->caldata->paprd_packet_sent = true;
+               set_bit(PAPRD_PACKET_SENT, &sc->sc_ah->caldata->cal_flags);
 
        if (!(tx_flags & ATH_TX_ERROR))
                /* Frame was ACKed */
@@ -2376,6 +2375,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 
        dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
        bf->bf_buf_addr = 0;
+       if (sc->tx99_state)
+               goto skip_tx_complete;
 
        if (bf->bf_state.bfs_paprd) {
                if (time_after(jiffies,
@@ -2388,6 +2389,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
                ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
                ath_tx_complete(sc, skb, tx_flags, txq);
        }
+skip_tx_complete:
        /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
         * accidentally reference it later.
         */
@@ -2746,3 +2748,46 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
                ath_txq_unlock(sc, txq);
        }
 }
+
+int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
+                   struct ath_tx_control *txctl)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_buf *bf;
+       int padpos, padsize;
+
+       padpos = ieee80211_hdrlen(hdr->frame_control);
+       padsize = padpos & 3;
+
+       if (padsize && skb->len > padpos) {
+               if (skb_headroom(skb) < padsize) {
+                       ath_dbg(common, XMIT,
+                               "tx99 padding failed\n");
+               return -EINVAL;
+               }
+
+               skb_push(skb, padsize);
+               memmove(skb->data, skb->data + padsize, padpos);
+       }
+
+       fi->keyix = ATH9K_TXKEYIX_INVALID;
+       fi->framelen = skb->len + FCS_LEN;
+       fi->keytype = ATH9K_KEY_TYPE_CLEAR;
+
+       bf = ath_tx_setup_buffer(sc, txctl->txq, NULL, skb);
+       if (!bf) {
+               ath_dbg(common, XMIT, "tx99 buffer setup failed\n");
+               return -EINVAL;
+       }
+
+       ath_set_rates(sc->tx99_vif, NULL, bf);
+
+       ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr);
+       ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum);
+
+       ath_tx_send_normal(sc, txctl->txq, NULL, skb);
+
+       return 0;
+}