}
 EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
 
-int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
+int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
+                       struct ath_tx_status *ts)
 {
        struct ar5416_desc *ads = AR5416DESC(ds);
 
        if ((ads->ds_txstatus9 & AR_TxDone) == 0)
                return -EINPROGRESS;
 
-       ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
-       ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
-       ds->ds_txstat.ts_status = 0;
-       ds->ds_txstat.ts_flags = 0;
+       ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
+       ts->ts_tstamp = ads->AR_SendTimestamp;
+       ts->ts_status = 0;
+       ts->ts_flags = 0;
 
        if (ads->ds_txstatus1 & AR_FrmXmitOK)
-               ds->ds_txstat.ts_status |= ATH9K_TX_ACKED;
+               ts->ts_status |= ATH9K_TX_ACKED;
        if (ads->ds_txstatus1 & AR_ExcessiveRetries)
-               ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
+               ts->ts_status |= ATH9K_TXERR_XRETRY;
        if (ads->ds_txstatus1 & AR_Filtered)
-               ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
+               ts->ts_status |= ATH9K_TXERR_FILT;
        if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
-               ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
+               ts->ts_status |= ATH9K_TXERR_FIFO;
                ath9k_hw_updatetxtriglevel(ah, true);
        }
        if (ads->ds_txstatus9 & AR_TxOpExceeded)
-               ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
+               ts->ts_status |= ATH9K_TXERR_XTXOP;
        if (ads->ds_txstatus1 & AR_TxTimerExpired)
-               ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+               ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
 
        if (ads->ds_txstatus1 & AR_DescCfgErr)
-               ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+               ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
        if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
-               ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+               ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
                ath9k_hw_updatetxtriglevel(ah, true);
        }
        if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
-               ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+               ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
                ath9k_hw_updatetxtriglevel(ah, true);
        }
        if (ads->ds_txstatus0 & AR_TxBaStatus) {
-               ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
-               ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
-               ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
+               ts->ts_flags |= ATH9K_TX_BA;
+               ts->ba_low = ads->AR_BaBitmapLow;
+               ts->ba_high = ads->AR_BaBitmapHigh;
        }
 
-       ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
-       switch (ds->ds_txstat.ts_rateindex) {
+       ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
+       switch (ts->ts_rateindex) {
        case 0:
-               ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
+               ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
                break;
        case 1:
-               ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
+               ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
                break;
        case 2:
-               ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
+               ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
                break;
        case 3:
-               ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
+               ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
                break;
        }
 
-       ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
-       ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
-       ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
-       ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
-       ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
-       ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
-       ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
-       ds->ds_txstat.evm0 = ads->AR_TxEVM0;
-       ds->ds_txstat.evm1 = ads->AR_TxEVM1;
-       ds->ds_txstat.evm2 = ads->AR_TxEVM2;
-       ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
-       ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
-       ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
-       ds->ds_txstat.ts_antenna = 0;
+       ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
+       ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
+       ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
+       ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
+       ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
+       ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
+       ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
+       ts->evm0 = ads->AR_TxEVM0;
+       ts->evm1 = ads->AR_TxEVM1;
+       ts->evm2 = ads->AR_TxEVM2;
+       ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
+       ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
+       ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
+       ts->ts_antenna = 0;
 
        return 0;
 }
 
                                  struct ath_atx_tid *tid,
                                  struct list_head *bf_head);
 static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
-                               struct ath_txq *txq,
-                               struct list_head *bf_q,
-                               int txok, int sendbar);
+                               struct ath_txq *txq, struct list_head *bf_q,
+                               struct ath_tx_status *ts, int txok, int sendbar);
 static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
                             struct list_head *head);
 static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf);
 static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
-                             int txok);
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
+                             struct ath_tx_status *ts, int txok);
+static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
                             int nbad, int txok, bool update_rc);
 
 enum {
 {
        struct ath_buf *bf;
        struct list_head bf_head;
+       struct ath_tx_status ts;
+
+       memset(&ts, 0, sizeof(ts));
        INIT_LIST_HEAD(&bf_head);
 
        for (;;) {
                        ath_tx_update_baw(sc, tid, bf->bf_seqno);
 
                spin_unlock(&txq->axq_lock);
-               ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
+               ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
                spin_lock(&txq->axq_lock);
        }
 
 
 static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                                 struct ath_buf *bf, struct list_head *bf_q,
-                                int txok)
+                                struct ath_tx_status *ts, int txok)
 {
        struct ath_node *an = NULL;
        struct sk_buff *skb;
        struct ieee80211_tx_info *tx_info;
        struct ath_atx_tid *tid = NULL;
        struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
-       struct ath_desc *ds = bf_last->bf_desc;
        struct list_head bf_head, bf_pending;
        u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
        u32 ba[WME_BA_BMP_SIZE >> 5];
        memset(ba, 0, WME_BA_BMP_SIZE >> 3);
 
        if (isaggr && txok) {
-               if (ATH_DS_TX_BA(ds)) {
-                       seq_st = ATH_DS_BA_SEQ(ds);
-                       memcpy(ba, ATH_DS_BA_BITMAP(ds),
-                              WME_BA_BMP_SIZE >> 3);
+               if (ts->ts_flags & ATH9K_TX_BA) {
+                       seq_st = ts->ts_seqnum;
+                       memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
                } else {
                        /*
                         * AR5416 can become deaf/mute when BA
        INIT_LIST_HEAD(&bf_pending);
        INIT_LIST_HEAD(&bf_head);
 
-       nbad = ath_tx_num_badfrms(sc, bf, txok);
+       nbad = ath_tx_num_badfrms(sc, bf, ts, txok);
        while (bf) {
                txfail = txpending = 0;
                bf_next = bf->bf_next;
                        acked_cnt++;
                } else {
                        if (!(tid->state & AGGR_CLEANUP) &&
-                           ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
+                           ts->ts_flags != ATH9K_TX_SW_ABORTED) {
                                if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
                                        ath_tx_set_retry(sc, txq, bf);
                                        txpending = 1;
                        spin_unlock_bh(&txq->axq_lock);
 
                        if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
-                               ath_tx_rc_status(bf, ds, nbad, txok, true);
+                               ath_tx_rc_status(bf, ts, nbad, txok, true);
                                rc_update = false;
                        } else {
-                               ath_tx_rc_status(bf, ds, nbad, txok, false);
+                               ath_tx_rc_status(bf, ts, nbad, txok, false);
                        }
 
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+                               !txfail, sendbar);
                } else {
                        /* retry the un-acked ones */
                        if (bf->bf_next == NULL && bf_last->bf_stale) {
                                        spin_unlock_bh(&txq->axq_lock);
 
                                        bf->bf_state.bf_type |= BUF_XRETRY;
-                                       ath_tx_rc_status(bf, ds, nbad,
+                                       ath_tx_rc_status(bf, ts, nbad,
                                                         0, false);
                                        ath_tx_complete_buf(sc, bf, txq,
-                                                           &bf_head, 0, 0);
+                                                           &bf_head, ts, 0, 0);
                                        break;
                                }
 
        struct ath_node *an = (struct ath_node *)sta->drv_priv;
        struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
        struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
+       struct ath_tx_status ts;
        struct ath_buf *bf;
        struct list_head bf_head;
+
+       memset(&ts, 0, sizeof(ts));
        INIT_LIST_HEAD(&bf_head);
 
        if (txtid->state & AGGR_CLEANUP)
                }
                list_move_tail(&bf->list, &bf_head);
                ath_tx_update_baw(sc, txtid, bf->bf_seqno);
-               ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
+               ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
        }
        spin_unlock_bh(&txq->axq_lock);
 
 {
        struct ath_buf *bf, *lastbf;
        struct list_head bf_head;
+       struct ath_tx_status ts;
+
+       memset(&ts, 0, sizeof(ts));
+       if (!retry_tx)
+               ts.ts_flags = ATH9K_TX_SW_ABORTED;
 
        INIT_LIST_HEAD(&bf_head);
 
                }
 
                lastbf = bf->bf_lastbf;
-               if (!retry_tx)
-                       lastbf->bf_desc->ds_txstat.ts_flags =
-                               ATH9K_TX_SW_ABORTED;
 
                /* remove ath_buf's of the same mpdu from txq */
                list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
                spin_unlock_bh(&txq->axq_lock);
 
                if (bf_isampdu(bf))
-                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0);
                else
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
        }
 
        spin_lock_bh(&txq->axq_lock);
 }
 
 static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
-                               struct ath_txq *txq,
-                               struct list_head *bf_q,
-                               int txok, int sendbar)
+                               struct ath_txq *txq, struct list_head *bf_q,
+                               struct ath_tx_status *ts, int txok, int sendbar)
 {
        struct sk_buff *skb = bf->bf_mpdu;
        unsigned long flags;
 
        dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
        ath_tx_complete(sc, skb, bf->aphy, tx_flags);
-       ath_debug_stat_tx(sc, txq, bf);
+       ath_debug_stat_tx(sc, txq, bf, ts);
 
        /*
         * Return the list of ath_buf of this mpdu to free queue
 }
 
 static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
-                             int txok)
+                             struct ath_tx_status *ts, int txok)
 {
-       struct ath_buf *bf_last = bf->bf_lastbf;
-       struct ath_desc *ds = bf_last->bf_desc;
        u16 seq_st = 0;
        u32 ba[WME_BA_BMP_SIZE >> 5];
        int ba_index;
        int nbad = 0;
        int isaggr = 0;
 
-       if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
+       if (ts->ts_flags == ATH9K_TX_SW_ABORTED)
                return 0;
 
        isaggr = bf_isaggr(bf);
        if (isaggr) {
-               seq_st = ATH_DS_BA_SEQ(ds);
-               memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
+               seq_st = ts->ts_seqnum;
+               memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
        }
 
        while (bf) {
        return nbad;
 }
 
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
+static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
                             int nbad, int txok, bool update_rc)
 {
        struct sk_buff *skb = bf->bf_mpdu;
        u8 i, tx_rateindex;
 
        if (txok)
-               tx_info->status.ack_signal = ds->ds_txstat.ts_rssi;
+               tx_info->status.ack_signal = ts->ts_rssi;
 
-       tx_rateindex = ds->ds_txstat.ts_rateindex;
+       tx_rateindex = ts->ts_rateindex;
        WARN_ON(tx_rateindex >= hw->max_rates);
 
-       if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
+       if (ts->ts_status & ATH9K_TXERR_FILT)
                tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
        if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc)
                tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
 
-       if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
+       if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
            (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
                if (ieee80211_is_data(hdr->frame_control)) {
-                       if (ds->ds_txstat.ts_flags &
+                       if (ts->ts_flags &
                            (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN))
                                tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN;
-                       if ((ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) ||
-                           (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO))
+                       if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
+                           (ts->ts_status & ATH9K_TXERR_FIFO))
                                tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
                        tx_info->status.ampdu_len = bf->bf_nframes;
                        tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
        struct ath_buf *bf, *lastbf, *bf_held = NULL;
        struct list_head bf_head;
        struct ath_desc *ds;
+       struct ath_tx_status *ts;
        int txok;
        int status;
 
 
                lastbf = bf->bf_lastbf;
                ds = lastbf->bf_desc;
+               ts = &ds->ds_us.tx;
 
-               status = ath9k_hw_txprocdesc(ah, ds);
+               status = ath9k_hw_txprocdesc(ah, ds, ts);
                if (status == -EINPROGRESS) {
                        spin_unlock_bh(&txq->axq_lock);
                        break;
                 * can disable RX.
                 */
                if (bf->bf_isnullfunc &&
-                   (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) {
+                   (ts->ts_status & ATH9K_TX_ACKED)) {
                        if ((sc->ps_flags & PS_ENABLED))
                                ath9k_enable_ps(sc);
                        else
                                &txq->axq_q, lastbf->list.prev);
 
                txq->axq_depth--;
-               txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK);
+               txok = !(ts->ts_status & ATH9K_TXERR_MASK);
                txq->axq_tx_inprogress = false;
                spin_unlock_bh(&txq->axq_lock);
 
                         * This frame is sent out as a single frame.
                         * Use hardware retry status for this frame.
                         */
-                       bf->bf_retries = ds->ds_txstat.ts_longretry;
-                       if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
+                       bf->bf_retries = ts->ts_longretry;
+                       if (ts->ts_status & ATH9K_TXERR_XRETRY)
                                bf->bf_state.bf_type |= BUF_XRETRY;
-                       ath_tx_rc_status(bf, ds, 0, txok, true);
+                       ath_tx_rc_status(bf, ts, 0, txok, true);
                }
 
                if (bf_isampdu(bf))
-                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, ts, txok);
                else
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, txok, 0);
 
                ath_wake_mac80211_queue(sc, txq);