staging: brcm80211: taking max AMPDU length advertized by peer into account
authorRoland Vossen <rvossen@broadcom.com>
Wed, 29 Jun 2011 23:46:46 +0000 (16:46 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 5 Jul 2011 16:57:12 +0000 (09:57 -0700)
AP advertizes max AMPDU rx length in beacon/probe response frame. Code now
uses this information to limit the length of AMPDU frames it transmits.

Signed-off-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/brcm80211/brcmsmac/ampdu.c
drivers/staging/brcm80211/brcmsmac/mac80211_if.c
drivers/staging/brcm80211/brcmsmac/pub.h
drivers/staging/brcm80211/brcmsmac/scb.h

index e9b78bf8e8cd3232bbc7088206d421ede14c1ef9..6271ad1095b1c7bdc34b0141e69563cc06170d5e 100644 (file)
@@ -220,9 +220,9 @@ static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
 
        scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
 
-       if (scb_ampdu->max_rxlen)
-               scb_ampdu->release =
-                   min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
+       if (scb_ampdu->max_rx_ampdu_bytes)
+               scb_ampdu->release = min_t(u8, scb_ampdu->release,
+                       scb_ampdu->max_rx_ampdu_bytes / 1600);
 
        scb_ampdu->release = min(scb_ampdu->release,
                                 ampdu->fifo_tb[TX_AC_BE_FIFO].
@@ -410,7 +410,8 @@ static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
 
 void
 brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
-                 u8 ba_wsize)          /* negotiated ba window size (in pdu) */
+       u8 ba_wsize,            /* negotiated ba window size (in pdu) */
+       uint max_rx_ampdu_bytes) /* from ht_cap in beacon */
 {
        scb_ampdu_t *scb_ampdu;
        scb_ampdu_tid_ini_t *ini;
@@ -428,6 +429,7 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
        ini->tid = tid;
        ini->scb = scb_ampdu->scb;
        ini->ba_wsize = ba_wsize;
+       scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
 }
 
 int
@@ -446,7 +448,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_c_txq_info *qi,
        bool rr = true, fbr = false;
        uint i, count = 0, fifo, seg_cnt = 0;
        u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
-       u32 ampdu_len, maxlen = 0;
+       u32 ampdu_len, max_ampdu_bytes = 0;
        d11txh_t *txh = NULL;
        u8 *plcp;
        struct ieee80211_hdr *h;
@@ -611,15 +613,10 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_c_txq_info *qi,
                        is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
                        sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
                        mcs = plcp0 & ~MIMO_PLCP_40MHZ;
-                       maxlen =
-                           min(scb_ampdu->max_rxlen,
+                       max_ampdu_bytes =
+                           min(scb_ampdu->max_rx_ampdu_bytes,
                                ampdu->max_txlen[mcs][is40][sgi]);
 
-                       /* XXX Fix me to honor real max_rxlen */
-                       /* can fix this as soon as ampdu_action() in mac80211.h
-                        * gets extra u8buf_size par */
-                       maxlen = 64 * 1024;
-
                        if (is40)
                                mimo_ctlchbw =
                                    CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
@@ -681,10 +678,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_c_txq_info *qi,
                                       AMPDU_MAX_MPDU_OVERHEAD;
                                plen = max(scb_ampdu->min_len, plen);
 
-                               if ((plen + ampdu_len) > maxlen) {
+                               if ((plen + ampdu_len) > max_ampdu_bytes) {
                                        p = NULL;
-                                       wiphy_err(wiphy, "%s: Bogus plen #1\n",
-                                               __func__);
                                        continue;
                                }
 
index 547df7569a1b46b0a2c2617c3ec5e616c883bcfb..c74c186e8d4f5852d9d95e225245845fc6ee5ebf 100644 (file)
@@ -659,10 +659,13 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
                /*
                 * BA window size from ADDBA response ('buf_size') defines how
                 * many outstanding MPDUs are allowed for the BA stream by
-                * recipient and traffic class.
+                * recipient and traffic class. 'ampdu_factor' gives maximum
+                * AMPDU size.
                 */
                LOCK(wl);
-               brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size);
+               brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size,
+                       (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+                        sta->ht_cap.ampdu_factor)) - 1);
                UNLOCK(wl);
                /* Power save wakeup */
                break;
index 14c0d20d43fb026084c5e0740ffc224c76caa266..58ae61d75880fc4f02b5e8debe5f5711b19bcc14 100644 (file)
@@ -627,7 +627,7 @@ extern void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs);
 extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
                            struct ieee80211_sta *sta, u16 tid);
 extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
-                                        u8 ba_wsize);
+                                        u8 ba_wsize, uint max_rx_ampdu_bytes);
 extern int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
                           int val);
 extern int brcms_c_get_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
index c2080e9e7935a559c728db1ac9315207a35cb9b0..62e005ede1c538fffded766a75ba874b81db1917 100644 (file)
@@ -40,7 +40,7 @@ struct scb_ampdu {
        u8 max_pdu;             /* max pdus allowed in ampdu */
        u8 release;             /* # of mpdus released at a time */
        u16 min_len;            /* min mpdu len to support the density */
-       u32 max_rxlen;  /* max ampdu rcv length; 8k, 16k, 32k, 64k */
+       u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */
        struct pktq txq;        /* sdu transmit queue pending aggregation */
 
        /* This could easily be a ini[] pointer and we keep this info in wl itself instead