ath9k: enable 3-stream and MCS16-23 support
authorFelix Fietkau <nbd@openwrt.org>
Sat, 17 Apr 2010 23:58:21 +0000 (23:58 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 17 Apr 2010 23:58:21 +0000 (23:58 +0000)
SVN-Revision: 20968

package/mac80211/patches/561-ath9k_streams_init.patch [new file with mode: 0644]
package/mac80211/patches/562-ath9k_4ms_limit_table.patch [new file with mode: 0644]
package/mac80211/patches/563-ath9k_bits_per_symbol.patch [new file with mode: 0644]
package/mac80211/patches/564-ath9k_mcs_mask_fix.patch [new file with mode: 0644]

diff --git a/package/mac80211/patches/561-ath9k_streams_init.patch b/package/mac80211/patches/561-ath9k_streams_init.patch
new file mode 100644 (file)
index 0000000..8228466
--- /dev/null
@@ -0,0 +1,72 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -176,6 +176,18 @@ static const struct ath_ops ath9k_common
+       .write = ath9k_iowrite32,
+ };
++static int count_streams(unsigned int chainmask, int max)
++{
++      int streams = 0;
++
++      do {
++              if (++streams == max)
++                      break;
++      } while ((chainmask = chainmask & (chainmask - 1)));
++
++      return streams;
++}
++
+ /**************************/
+ /*     Initialization     */
+ /**************************/
+@@ -183,8 +195,10 @@ static const struct ath_ops ath9k_common
+ static void setup_ht_cap(struct ath_softc *sc,
+                        struct ieee80211_sta_ht_cap *ht_info)
+ {
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      struct ath_hw *ah = sc->sc_ah;
++      struct ath_common *common = ath9k_hw_common(ah);
+       u8 tx_streams, rx_streams;
++      int i, max_streams;
+       ht_info->ht_supported = true;
+       ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+@@ -198,25 +212,28 @@ static void setup_ht_cap(struct ath_soft
+       ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+       ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
++      if (AR_SREV_9300_20_OR_LATER(ah))
++              max_streams = 3;
++      else
++              max_streams = 2;
++
+       /* set up supported mcs set */
+       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+-      tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ?
+-                   1 : 2;
+-      rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ?
+-                   1 : 2;
++      tx_streams = count_streams(common->tx_chainmask, max_streams);
++      rx_streams = count_streams(common->rx_chainmask, max_streams);
++
++      ath_print(common, ATH_DBG_CONFIG,
++                "TX streams %d, RX streams: %d\n",
++                tx_streams, rx_streams);
+       if (tx_streams != rx_streams) {
+-              ath_print(common, ATH_DBG_CONFIG,
+-                        "TX streams %d, RX streams: %d\n",
+-                        tx_streams, rx_streams);
+               ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+               ht_info->mcs.tx_params |= ((tx_streams - 1) <<
+                               IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+       }
+-      ht_info->mcs.rx_mask[0] = 0xff;
+-      if (rx_streams >= 2)
+-              ht_info->mcs.rx_mask[1] = 0xff;
++      for (i = 0; i < rx_streams; i++)
++              ht_info->mcs.rx_mask[i] = 0xff;
+       ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
+ }
diff --git a/package/mac80211/patches/562-ath9k_4ms_limit_table.patch b/package/mac80211/patches/562-ath9k_4ms_limit_table.patch
new file mode 100644 (file)
index 0000000..2eee096
--- /dev/null
@@ -0,0 +1,67 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -71,24 +71,36 @@ static void ath_tx_rc_status(struct ath_
+                            int nbad, int txok, bool update_rc);
+ enum {
+-      MCS_DEFAULT,
++      MCS_HT20,
++      MCS_HT20_SGI,
+       MCS_HT40,
+       MCS_HT40_SGI,
+ };
+-static int ath_max_4ms_framelen[3][16] = {
+-      [MCS_DEFAULT] = {
+-              3216,  6434,  9650,  12868, 19304, 25740,  28956,  32180,
+-              6430,  12860, 19300, 25736, 38600, 51472,  57890,  64320,
++static u16 ath_max_4ms_framelen[4][32] = {
++      [MCS_HT20] = {
++              3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
++              6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
++              9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
++              12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
++      },
++      [MCS_HT20_SGI] = {
++              3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
++              7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
++              10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
++              14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
+       },
+       [MCS_HT40] = {
+-              6684,  13368, 20052, 26738, 40104, 53476,  60156,  66840,
+-              13360, 26720, 40080, 53440, 80160, 106880, 120240, 133600,
++              6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
++              13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
++              20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
++              26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
+       },
+       [MCS_HT40_SGI] = {
+-              /* TODO: Only MCS 7 and 15 updated, recalculate the rest */
+-              6684,  13368, 20052, 26738, 40104, 53476,  60156,  74200,
+-              13360, 26720, 40080, 53440, 80160, 106880, 120240, 148400,
++              7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
++              14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
++              22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
++              29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
+       }
+ };
+@@ -538,12 +550,13 @@ static u32 ath_lookup_rate(struct ath_so
+                               break;
+                       }
+-                      if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+-                              modeidx = MCS_HT40_SGI;
+-                      else if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
++                      if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+                               modeidx = MCS_HT40;
+                       else
+-                              modeidx = MCS_DEFAULT;
++                              modeidx = MCS_HT20;
++
++                      if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
++                              modeidx++;
+                       frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
+                       max_4ms_framelen = min(max_4ms_framelen, frmlen);
diff --git a/package/mac80211/patches/563-ath9k_bits_per_symbol.patch b/package/mac80211/patches/563-ath9k_bits_per_symbol.patch
new file mode 100644 (file)
index 0000000..d842e40
--- /dev/null
@@ -0,0 +1,64 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -34,7 +34,7 @@
+ #define OFDM_SIFS_TIME            16
+-static u32 bits_per_symbol[][2] = {
++static u16 bits_per_symbol[][2] = {
+       /* 20MHz 40MHz */
+       {    26,   54 },     /*  0: BPSK */
+       {    52,  108 },     /*  1: QPSK 1/2 */
+@@ -44,14 +44,6 @@ static u32 bits_per_symbol[][2] = {
+       {   208,  432 },     /*  5: 64-QAM 2/3 */
+       {   234,  486 },     /*  6: 64-QAM 3/4 */
+       {   260,  540 },     /*  7: 64-QAM 5/6 */
+-      {    52,  108 },     /*  8: BPSK */
+-      {   104,  216 },     /*  9: QPSK 1/2 */
+-      {   156,  324 },     /* 10: QPSK 3/4 */
+-      {   208,  432 },     /* 11: 16-QAM 1/2 */
+-      {   312,  648 },     /* 12: 16-QAM 3/4 */
+-      {   416,  864 },     /* 13: 64-QAM 2/3 */
+-      {   468,  972 },     /* 14: 64-QAM 3/4 */
+-      {   520, 1080 },     /* 15: 64-QAM 5/6 */
+ };
+ #define IS_HT_RATE(_rate)     ((_rate) & 0x80)
+@@ -601,7 +593,7 @@ static int ath_compute_num_delims(struct
+       u32 nsymbits, nsymbols;
+       u16 minlen;
+       u8 flags, rix;
+-      int width, half_gi, ndelim, mindelim;
++      int width, streams, half_gi, ndelim, mindelim;
+       /* Select standard number of delimiters based on frame length alone */
+       ndelim = ATH_AGGR_GET_NDELIM(frmlen);
+@@ -641,7 +633,8 @@ static int ath_compute_num_delims(struct
+       if (nsymbols == 0)
+               nsymbols = 1;
+-      nsymbits = bits_per_symbol[rix][width];
++      streams = HT_RC_2_STREAMS(rix);
++      nsymbits = bits_per_symbol[rix % 8][width] * streams;
+       minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
+       if (frmlen < minlen) {
+@@ -1533,8 +1526,9 @@ static u32 ath_pkt_duration(struct ath_s
+       pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
+       /* find number of symbols: PLCP + data */
++      streams = HT_RC_2_STREAMS(rix);
+       nbits = (pktlen << 3) + OFDM_PLCP_BITS;
+-      nsymbits = bits_per_symbol[rix][width];
++      nsymbits = bits_per_symbol[rix % 8][width] * streams;
+       nsymbols = (nbits + nsymbits - 1) / nsymbits;
+       if (!half_gi)
+@@ -1543,7 +1537,6 @@ static u32 ath_pkt_duration(struct ath_s
+               duration = SYMBOL_TIME_HALFGI(nsymbols);
+       /* addup duration for legacy/ht training and signal fields */
+-      streams = HT_RC_2_STREAMS(rix);
+       duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+       return duration;
diff --git a/package/mac80211/patches/564-ath9k_mcs_mask_fix.patch b/package/mac80211/patches/564-ath9k_mcs_mask_fix.patch
new file mode 100644 (file)
index 0000000..4d0ac2d
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -19,7 +19,7 @@
+ #define BITS_PER_BYTE           8
+ #define OFDM_PLCP_BITS          22
+-#define HT_RC_2_MCS(_rc)        ((_rc) & 0x0f)
++#define HT_RC_2_MCS(_rc)        ((_rc) & 0x1f)
+ #define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
+ #define L_STF                   8
+ #define L_LTF                   8