staging: brcm80211: lower number of wlc_bsscfg.h includes
[pandora-kernel.git] / drivers / staging / brcm80211 / brcmsmac / wlc_ampdu.c
index 19e22c8..c6cdcd9 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <net/mac80211.h>
 
-#include <osl.h>
 #include <bcmdefs.h>
 #include <bcmutils.h>
 #include <siutils.h>
@@ -35,9 +34,8 @@
 #include "wlc_antsel.h"
 #include "wl_export.h"
 #include "wl_dbg.h"
-#include "wlc_bsscfg.h"
 #include "wlc_channel.h"
-#include "wlc_mac80211.h"
+#include "wlc_main.h"
 #include "wlc_ampdu.h"
 
 /*
@@ -201,9 +199,9 @@ struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
        ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
        /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
        if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
-               ampdu->rx_factor = AMPDU_RX_FACTOR_32K;
+               ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
        else
-               ampdu->rx_factor = AMPDU_RX_FACTOR_64K;
+               ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
        ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
        ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
 
@@ -494,7 +492,6 @@ wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
              struct sk_buff **pdu, int prec)
 {
        struct wlc_info *wlc;
-       struct osl_info *osh;
        struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
        u8 tid, ndelim;
        int err = 0;
@@ -526,7 +523,6 @@ wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
        u16 qlen;
 
        wlc = ampdu->wlc;
-       osh = wlc->osh;
        p = *pdu;
 
        ASSERT(p);
@@ -634,17 +630,16 @@ wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
                 * test whether need to break or change the epoch
                 */
                if (count == 0) {
-                       u16 fc;
                        mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
                        /* refill the bits since might be a retx mpdu */
                        mcl |= TXC_STARTMSDU;
                        rts = (struct ieee80211_rts *)&txh->rts_frame;
-                       fc = le16_to_cpu(rts->frame_control);
-                       if ((fc & FC_KIND_MASK) == FC_RTS) {
+
+                       if (ieee80211_is_rts(rts->frame_control)) {
                                mcl |= TXC_SENDRTS;
                                use_rts = true;
                        }
-                       if ((fc & FC_KIND_MASK) == FC_CTS) {
+                       if (ieee80211_is_cts(rts->frame_control)) {
                                mcl |= TXC_SENDCTS;
                                use_cts = true;
                        }
@@ -904,13 +899,7 @@ wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
 
        tx_info = IEEE80211_SKB_CB(p);
        ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
-       ASSERT(scb);
-       ASSERT(scb->magic == SCB_MAGIC);
        ASSERT(txs->status & TX_STATUS_AMPDU);
-       scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-       ASSERT(scb_ampdu);
-       ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
-       ASSERT(ini->scb == scb);
 
        /* BMAC_NOTE: For the split driver, second level txstatus comes later
         * So if the ACK was received then wait for the second level else just
@@ -920,9 +909,7 @@ wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
                u8 status_delay = 0;
 
                /* wait till the next 8 bytes of txstatus is available */
-               while (((s1 =
-                        R_REG(wlc->osh,
-                              &wlc->regs->frmtxstatus)) & TXS_V) == 0) {
+               while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
                        udelay(1);
                        status_delay++;
                        if (status_delay > 10) {
@@ -933,10 +920,36 @@ wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
 
                ASSERT(!(s1 & TX_STATUS_INTERMEDIATE));
                ASSERT(s1 & TX_STATUS_AMPDU);
-               s2 = R_REG(wlc->osh, &wlc->regs->frmtxstatus2);
+               s2 = R_REG(&wlc->regs->frmtxstatus2);
        }
 
-       wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+       if (likely(scb)) {
+               ASSERT(scb->magic == SCB_MAGIC);
+               scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+               ASSERT(scb_ampdu);
+               ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
+               ASSERT(ini->scb == scb);
+               wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+       } else {
+               /* loop through all pkts and free */
+               u8 queue = txs->frameid & TXFID_QUEUE_MASK;
+               d11txh_t *txh;
+               u16 mcl;
+               while (p) {
+                       tx_info = IEEE80211_SKB_CB(p);
+                       txh = (d11txh_t *) p->data;
+                       mcl = le16_to_cpu(txh->MacTxControlLow);
+                       ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
+                       pkt_buf_free_skb(p);
+                       /* break out if last packet of ampdu */
+                       if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+                           TXC_AMPDU_LAST)
+                               break;
+                       p = GETNEXTTXP(wlc, queue);
+                       ASSERT(p != NULL);
+               }
+               wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
+       }
        wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
 }
 
@@ -1072,7 +1085,7 @@ wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
                                 wlc->pub->unit, txs->phyerr);
 
                        if (WL_ERROR_ON()) {
-                               prpkt("txpkt (AMPDU)", wlc->osh, p);
+                               prpkt("txpkt (AMPDU)", p);
                                wlc_print_txdesc((d11txh_t *) p->data);
                        }
                        wlc_print_txstatus(txs);
@@ -1200,7 +1213,7 @@ ampdu_cleanup_tid_ini(struct ampdu_info *ampdu, scb_ampdu_t *scb_ampdu, u8 tid,
        ASSERT(ini == &scb_ampdu->ini[ini->tid]);
 
        /* free all buffered tx packets */
-       pktq_pflush(ampdu->wlc->osh, &scb_ampdu->txq, ini->tid, true, NULL, 0);
+       pktq_pflush(&scb_ampdu->txq, ini->tid, true, NULL, 0);
 }
 
 /* initialize the initiator code for tid */
@@ -1340,8 +1353,8 @@ void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
        struct wlc_info *wlc = ampdu->wlc;
 
        /* Extend ucode internal watchdog timer to match larger received frames */
-       if ((ampdu->rx_factor & HT_PARAMS_RX_FACTOR_MASK) ==
-           AMPDU_RX_FACTOR_64K) {
+       if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
+           IEEE80211_HT_MAX_AMPDU_64K) {
                wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
                wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
        } else {
@@ -1349,3 +1362,60 @@ void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
                wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
        }
 }
+
+struct cb_del_ampdu_pars {
+       struct ieee80211_sta *sta;
+       u16 tid;
+};
+
+/*
+ * callback function that helps flushing ampdu packets from a priority queue
+ */
+static bool cb_del_ampdu_pkt(void *p, int arg_a)
+{
+       struct sk_buff *mpdu = (struct sk_buff *)p;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
+       struct cb_del_ampdu_pars *ampdu_pars =
+                                (struct cb_del_ampdu_pars *)arg_a;
+       bool rc;
+
+       rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
+       rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
+                   tx_info->control.sta == ampdu_pars->sta);
+       rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
+       return rc;
+}
+
+/*
+ * callback function that helps invalidating ampdu packets in a DMA queue
+ */
+static void dma_cb_fn_ampdu(void *txi, void *arg_a)
+{
+       struct ieee80211_sta *sta = arg_a;
+       struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
+
+       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
+           (tx_info->control.sta == sta || sta == NULL))
+               tx_info->control.sta = NULL;
+}
+
+/*
+ * When a remote party is no longer available for ampdu communication, any
+ * pending tx ampdu packets in the driver have to be flushed.
+ */
+void wlc_ampdu_flush(struct wlc_info *wlc,
+                    struct ieee80211_sta *sta, u16 tid)
+{
+       struct wlc_txq_info *qi = wlc->active_queue;
+       struct pktq *pq = &qi->q;
+       int prec;
+       struct cb_del_ampdu_pars ampdu_pars;
+
+       ampdu_pars.sta = sta;
+       ampdu_pars.tid = tid;
+       for (prec = 0; prec < pq->num_prec; prec++) {
+               pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
+                           (int)&ampdu_pars);
+       }
+       wlc_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
+}