2013-02-08 13:13:20

by Felix Fietkau

[permalink] [raw]
Subject: [RFC] ath9k: remove ath9k_rate_control

In many tests throughput with ath9k_rate_control has been shown to be
worse than with minstrel_ht (the mac8021 default RC).

This module also has some other problems, like starting to use the
highest possible rate early in the connection, causing problems with
reliability of connection/authentication attempts.

It also has a much more limited search space, ignoring many potentially
useful rates, caused by the design decision to operate on a sorted rate
set with the assumption that higher rates are always more unreliable
than lower rates. In some scenarios this assumption is not true, and
this can cause it to fall back to a really bad rate.

minstrel_ht has been tested extensively in AP and client mode by lots of
users (mostly in the OpenWrt project, where it has been the default for
years).

The only advantage that ath9k_rate_control previously had over minstrel_ht
was the support for using CCK rates as fall back in case MCS rates got
too bad, but this has now also been taken care of.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/Kconfig | 8 -
drivers/net/wireless/ath/ath9k/Makefile | 1 -
drivers/net/wireless/ath/ath9k/debug.h | 1 -
drivers/net/wireless/ath/ath9k/hw.c | 15 +-
drivers/net/wireless/ath/ath9k/hw.h | 4 +-
drivers/net/wireless/ath/ath9k/init.c | 17 +-
drivers/net/wireless/ath/ath9k/rc.c | 1501 -------------------------------
drivers/net/wireless/ath/ath9k/rc.h | 248 -----
drivers/net/wireless/ath/ath9k/xmit.c | 9 +-
9 files changed, 10 insertions(+), 1794 deletions(-)
delete mode 100644 drivers/net/wireless/ath/ath9k/rc.c
delete mode 100644 drivers/net/wireless/ath/ath9k/rc.h

diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 17507dc..037d919 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -92,14 +92,6 @@ config ATH9K_MAC_DEBUG
This option enables collection of statistics for Rx/Tx status
data and some other MAC related statistics

-config ATH9K_RATE_CONTROL
- bool "Atheros ath9k rate control"
- depends on ATH9K
- default y
- ---help---
- Say Y, if you want to use the ath9k specific rate control
- module instead of minstrel_ht.
-
config ATH9K_HTC
tristate "Atheros HTC based wireless cards support"
depends on USB && MAC80211
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 2ad8f94..655e21d 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -8,7 +8,6 @@ ath9k-y += beacon.o \
antenna.o

ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
-ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 410d6d8..06b5760 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -18,7 +18,6 @@
#define DEBUG_H

#include "hw.h"
-#include "rc.h"
#include "dfs_debug.h"

struct ath_txq;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 42cf3c7..6491973 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -21,7 +21,6 @@

#include "hw.h"
#include "hw-ops.h"
-#include "rc.h"
#include "ar9003_mac.h"
#include "ar9003_mci.h"
#include "ar9003_phy.h"
@@ -230,7 +229,7 @@ u32 ath9k_hw_reverse_bits(u32 val, u32 n)
}

u16 ath9k_hw_computetxtime(struct ath_hw *ah,
- u8 phy, int kbps,
+ bool cck, int kbps,
u32 frameLen, u16 rateix,
bool shortPreamble)
{
@@ -239,15 +238,13 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah,
if (kbps == 0)
return 0;

- switch (phy) {
- case WLAN_RC_PHY_CCK:
+ if (cck) {
phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
if (shortPreamble)
phyTime >>= 1;
numBits = frameLen << 3;
txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
- break;
- case WLAN_RC_PHY_OFDM:
+ } else {
if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) {
bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
numBits = OFDM_PLCP_BITS + (frameLen << 3);
@@ -270,12 +267,6 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah,
txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
+ (numSymbols * OFDM_SYMBOL_TIME);
}
- break;
- default:
- ath_err(ath9k_hw_common(ah),
- "Unknown phy %u (rate ix %u)\n", phy, rateix);
- txTime = 0;
- break;
}

return txTime;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 784e81c..24f5b70 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -22,6 +22,8 @@
#include <linux/io.h>
#include <linux/firmware.h>

+struct ath_softc;
+
#include "mac.h"
#include "ani.h"
#include "eeprom.h"
@@ -1013,7 +1015,7 @@ void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array,
int column, unsigned int *writecnt);
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
u16 ath9k_hw_computetxtime(struct ath_hw *ah,
- u8 phy, int kbps,
+ bool cck, int kbps,
u32 frameLen, u16 rateix, bool shortPreamble);
void ath9k_hw_get_channel_centers(struct ath_hw *ah,
struct ath9k_channel *chan,
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index af932c9..c86cc70 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -809,10 +809,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
sc->ant_rx = hw->wiphy->available_antennas_rx;
sc->ant_tx = hw->wiphy->available_antennas_tx;

-#ifdef CONFIG_ATH9K_RATE_CONTROL
- hw->rate_control_algorithm = "ath9k_rate_control";
-#endif
-
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&sc->sbands[IEEE80211_BAND_2GHZ];
@@ -952,19 +948,11 @@ static int __init ath9k_init(void)
{
int error;

- /* Register rate control algorithm */
- error = ath_rate_control_register();
- if (error != 0) {
- pr_err("Unable to register rate control algorithm: %d\n",
- error);
- goto err_out;
- }
-
error = ath_pci_init();
if (error < 0) {
pr_err("No PCI devices found, driver not installed\n");
error = -ENODEV;
- goto err_rate_unregister;
+ goto err_out;
}

error = ath_ahb_init();
@@ -978,8 +966,6 @@ static int __init ath9k_init(void)
err_pci_exit:
ath_pci_exit();

- err_rate_unregister:
- ath_rate_control_unregister();
err_out:
return error;
}
@@ -990,7 +976,6 @@ static void __exit ath9k_exit(void)
is_ath9k_unloaded = true;
ath_ahb_exit();
ath_pci_exit();
- ath_rate_control_unregister();
pr_info("%s: Driver unloaded\n", dev_info);
}
module_exit(ath9k_exit);
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
deleted file mode 100644
index 714558d..0000000
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ /dev/null
@@ -1,1501 +0,0 @@
-/*
- * Copyright (c) 2004 Video54 Technologies, Inc.
- * Copyright (c) 2004-2011 Atheros Communications, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-
-#include "ath9k.h"
-
-static const struct ath_rate_table ar5416_11na_ratetable = {
- 68,
- 8, /* MCS start */
- {
- [0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000,
- 5400, 0, 12 }, /* 6 Mb */
- [1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000,
- 7800, 1, 18 }, /* 9 Mb */
- [2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
- 10000, 2, 24 }, /* 12 Mb */
- [3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
- 13900, 3, 36 }, /* 18 Mb */
- [4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
- 17300, 4, 48 }, /* 24 Mb */
- [5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
- 23000, 5, 72 }, /* 36 Mb */
- [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
- 27400, 6, 96 }, /* 48 Mb */
- [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
- 29300, 7, 108 }, /* 54 Mb */
- [8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500,
- 6400, 0, 0 }, /* 6.5 Mb */
- [9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
- 12700, 1, 1 }, /* 13 Mb */
- [10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
- 18800, 2, 2 }, /* 19.5 Mb */
- [11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
- 25000, 3, 3 }, /* 26 Mb */
- [12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
- 36700, 4, 4 }, /* 39 Mb */
- [13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
- 48100, 5, 5 }, /* 52 Mb */
- [14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
- 53500, 6, 6 }, /* 58.5 Mb */
- [15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
- 59000, 7, 7 }, /* 65 Mb */
- [16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
- 65400, 7, 7 }, /* 75 Mb */
- [17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
- 12700, 8, 8 }, /* 13 Mb */
- [18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
- 24800, 9, 9 }, /* 26 Mb */
- [19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
- 36600, 10, 10 }, /* 39 Mb */
- [20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
- 48100, 11, 11 }, /* 52 Mb */
- [21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
- 69500, 12, 12 }, /* 78 Mb */
- [22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
- 89500, 13, 13 }, /* 104 Mb */
- [23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
- 98900, 14, 14 }, /* 117 Mb */
- [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
- 108300, 15, 15 }, /* 130 Mb */
- [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
- 120000, 15, 15 }, /* 144.4 Mb */
- [26] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
- 17400, 16, 16 }, /* 19.5 Mb */
- [27] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
- 35100, 17, 17 }, /* 39 Mb */
- [28] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
- 52600, 18, 18 }, /* 58.5 Mb */
- [29] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
- 70400, 19, 19 }, /* 78 Mb */
- [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
- 104900, 20, 20 }, /* 117 Mb */
- [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
- 115800, 20, 20 }, /* 130 Mb*/
- [32] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
- 137200, 21, 21 }, /* 156 Mb */
- [33] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
- 151100, 21, 21 }, /* 173.3 Mb */
- [34] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
- 152800, 22, 22 }, /* 175.5 Mb */
- [35] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
- 168400, 22, 22 }, /* 195 Mb*/
- [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
- 168400, 23, 23 }, /* 195 Mb */
- [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
- 185000, 23, 23 }, /* 216.7 Mb */
- [38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
- 13200, 0, 0 }, /* 13.5 Mb*/
- [39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
- 25900, 1, 1 }, /* 27.0 Mb*/
- [40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
- 38600, 2, 2 }, /* 40.5 Mb*/
- [41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
- 49800, 3, 3 }, /* 54 Mb */
- [42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
- 72200, 4, 4 }, /* 81 Mb */
- [43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000,
- 92900, 5, 5 }, /* 108 Mb */
- [44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
- 102700, 6, 6 }, /* 121.5 Mb*/
- [45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
- 112000, 7, 7 }, /* 135 Mb */
- [46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
- 122000, 7, 7 }, /* 150 Mb */
- [47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
- 25800, 8, 8 }, /* 27 Mb */
- [48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
- 49800, 9, 9 }, /* 54 Mb */
- [49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
- 71900, 10, 10 }, /* 81 Mb */
- [50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
- 92500, 11, 11 }, /* 108 Mb */
- [51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
- 130300, 12, 12 }, /* 162 Mb */
- [52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
- 162800, 13, 13 }, /* 216 Mb */
- [53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
- 178200, 14, 14 }, /* 243 Mb */
- [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
- 192100, 15, 15 }, /* 270 Mb */
- [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
- 207000, 15, 15 }, /* 300 Mb */
- [56] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
- 36100, 16, 16 }, /* 40.5 Mb */
- [57] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
- 72900, 17, 17 }, /* 81 Mb */
- [58] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
- 108300, 18, 18 }, /* 121.5 Mb */
- [59] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
- 142000, 19, 19 }, /* 162 Mb */
- [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
- 205100, 20, 20 }, /* 243 Mb */
- [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
- 224700, 20, 20 }, /* 270 Mb */
- [62] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
- 263100, 21, 21 }, /* 324 Mb */
- [63] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
- 288000, 21, 21 }, /* 360 Mb */
- [64] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
- 290700, 22, 22 }, /* 364.5 Mb */
- [65] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
- 317200, 22, 22 }, /* 405 Mb */
- [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
- 317200, 23, 23 }, /* 405 Mb */
- [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
- 346400, 23, 23 }, /* 450 Mb */
- },
- 50, /* probe interval */
- WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
-};
-
-/* 4ms frame limit not used for NG mode. The values filled
- * for HT are the 64K max aggregate limit */
-
-static const struct ath_rate_table ar5416_11ng_ratetable = {
- 72,
- 12, /* MCS start */
- {
- [0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000,
- 900, 0, 2 }, /* 1 Mb */
- [1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000,
- 1900, 1, 4 }, /* 2 Mb */
- [2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500,
- 4900, 2, 11 }, /* 5.5 Mb */
- [3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000,
- 8100, 3, 22 }, /* 11 Mb */
- [4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000,
- 5400, 4, 12 }, /* 6 Mb */
- [5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000,
- 7800, 5, 18 }, /* 9 Mb */
- [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
- 10100, 6, 24 }, /* 12 Mb */
- [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
- 14100, 7, 36 }, /* 18 Mb */
- [8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
- 17700, 8, 48 }, /* 24 Mb */
- [9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
- 23700, 9, 72 }, /* 36 Mb */
- [10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
- 27400, 10, 96 }, /* 48 Mb */
- [11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
- 30900, 11, 108 }, /* 54 Mb */
- [12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500,
- 6400, 0, 0 }, /* 6.5 Mb */
- [13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
- 12700, 1, 1 }, /* 13 Mb */
- [14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
- 18800, 2, 2 }, /* 19.5 Mb*/
- [15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
- 25000, 3, 3 }, /* 26 Mb */
- [16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
- 36700, 4, 4 }, /* 39 Mb */
- [17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
- 48100, 5, 5 }, /* 52 Mb */
- [18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
- 53500, 6, 6 }, /* 58.5 Mb */
- [19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
- 59000, 7, 7 }, /* 65 Mb */
- [20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
- 65400, 7, 7 }, /* 65 Mb*/
- [21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
- 12700, 8, 8 }, /* 13 Mb */
- [22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
- 24800, 9, 9 }, /* 26 Mb */
- [23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
- 36600, 10, 10 }, /* 39 Mb */
- [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
- 48100, 11, 11 }, /* 52 Mb */
- [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
- 69500, 12, 12 }, /* 78 Mb */
- [26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
- 89500, 13, 13 }, /* 104 Mb */
- [27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
- 98900, 14, 14 }, /* 117 Mb */
- [28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
- 108300, 15, 15 }, /* 130 Mb */
- [29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
- 120000, 15, 15 }, /* 144.4 Mb */
- [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
- 17400, 16, 16 }, /* 19.5 Mb */
- [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
- 35100, 17, 17 }, /* 39 Mb */
- [32] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
- 52600, 18, 18 }, /* 58.5 Mb */
- [33] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
- 70400, 19, 19 }, /* 78 Mb */
- [34] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
- 104900, 20, 20 }, /* 117 Mb */
- [35] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
- 115800, 20, 20 }, /* 130 Mb */
- [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
- 137200, 21, 21 }, /* 156 Mb */
- [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
- 151100, 21, 21 }, /* 173.3 Mb */
- [38] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
- 152800, 22, 22 }, /* 175.5 Mb */
- [39] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
- 168400, 22, 22 }, /* 195 Mb */
- [40] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
- 168400, 23, 23 }, /* 195 Mb */
- [41] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
- 185000, 23, 23 }, /* 216.7 Mb */
- [42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
- 13200, 0, 0 }, /* 13.5 Mb */
- [43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
- 25900, 1, 1 }, /* 27.0 Mb */
- [44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
- 38600, 2, 2 }, /* 40.5 Mb */
- [45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
- 49800, 3, 3 }, /* 54 Mb */
- [46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
- 72200, 4, 4 }, /* 81 Mb */
- [47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000,
- 92900, 5, 5 }, /* 108 Mb */
- [48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
- 102700, 6, 6 }, /* 121.5 Mb */
- [49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
- 112000, 7, 7 }, /* 135 Mb */
- [50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
- 122000, 7, 7 }, /* 150 Mb */
- [51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
- 25800, 8, 8 }, /* 27 Mb */
- [52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
- 49800, 9, 9 }, /* 54 Mb */
- [53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
- 71900, 10, 10 }, /* 81 Mb */
- [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
- 92500, 11, 11 }, /* 108 Mb */
- [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
- 130300, 12, 12 }, /* 162 Mb */
- [56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
- 162800, 13, 13 }, /* 216 Mb */
- [57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
- 178200, 14, 14 }, /* 243 Mb */
- [58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
- 192100, 15, 15 }, /* 270 Mb */
- [59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
- 207000, 15, 15 }, /* 300 Mb */
- [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
- 36100, 16, 16 }, /* 40.5 Mb */
- [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
- 72900, 17, 17 }, /* 81 Mb */
- [62] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
- 108300, 18, 18 }, /* 121.5 Mb */
- [63] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
- 142000, 19, 19 }, /* 162 Mb */
- [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
- 205100, 20, 20 }, /* 243 Mb */
- [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
- 224700, 20, 20 }, /* 270 Mb */
- [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
- 263100, 21, 21 }, /* 324 Mb */
- [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
- 288000, 21, 21 }, /* 360 Mb */
- [68] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
- 290700, 22, 22 }, /* 364.5 Mb */
- [69] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
- 317200, 22, 22 }, /* 405 Mb */
- [70] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
- 317200, 23, 23 }, /* 405 Mb */
- [71] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
- 346400, 23, 23 }, /* 450 Mb */
- },
- 50, /* probe interval */
- WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
-};
-
-static const struct ath_rate_table ar5416_11a_ratetable = {
- 8,
- 0,
- {
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
- 5400, 0, 12},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
- 7800, 1, 18},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
- 10000, 2, 24},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
- 13900, 3, 36},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
- 17300, 4, 48},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
- 23000, 5, 72},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
- 27400, 6, 96},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
- 29300, 7, 108},
- },
- 50, /* probe interval */
- 0, /* Phy rates allowed initially */
-};
-
-static const struct ath_rate_table ar5416_11g_ratetable = {
- 12,
- 0,
- {
- { RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
- 900, 0, 2},
- { RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
- 1900, 1, 4},
- { RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
- 4900, 2, 11},
- { RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
- 8100, 3, 22},
- { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
- 5400, 4, 12},
- { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
- 7800, 5, 18},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
- 10000, 6, 24},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
- 13900, 7, 36},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
- 17300, 8, 48},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
- 23000, 9, 72},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
- 27400, 10, 96},
- { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
- 29300, 11, 108},
- },
- 50, /* probe interval */
- 0, /* Phy rates allowed initially */
-};
-
-static int ath_rc_get_rateindex(struct ath_rate_priv *ath_rc_priv,
- struct ieee80211_tx_rate *rate)
-{
- const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
- int rix, i, idx = 0;
-
- if (!(rate->flags & IEEE80211_TX_RC_MCS))
- return rate->idx;
-
- for (i = 0; i < ath_rc_priv->max_valid_rate; i++) {
- idx = ath_rc_priv->valid_rate_index[i];
-
- if (WLAN_RC_PHY_HT(rate_table->info[idx].phy) &&
- rate_table->info[idx].ratecode == rate->idx)
- break;
- }
-
- rix = idx;
-
- if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
- rix++;
-
- return rix;
-}
-
-static void ath_rc_sort_validrates(struct ath_rate_priv *ath_rc_priv)
-{
- const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
- u8 i, j, idx, idx_next;
-
- for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
- for (j = 0; j <= i-1; j++) {
- idx = ath_rc_priv->valid_rate_index[j];
- idx_next = ath_rc_priv->valid_rate_index[j+1];
-
- if (rate_table->info[idx].ratekbps >
- rate_table->info[idx_next].ratekbps) {
- ath_rc_priv->valid_rate_index[j] = idx_next;
- ath_rc_priv->valid_rate_index[j+1] = idx;
- }
- }
- }
-}
-
-static inline
-int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table,
- struct ath_rate_priv *ath_rc_priv,
- u8 cur_valid_txrate,
- u8 *next_idx)
-{
- u8 i;
-
- for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
- if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
- *next_idx = ath_rc_priv->valid_rate_index[i+1];
- return 1;
- }
- }
-
- /* No more valid rates */
- *next_idx = 0;
-
- return 0;
-}
-
-/* Return true only for single stream */
-
-static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
-{
- if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
- return 0;
- if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
- return 0;
- if (WLAN_RC_PHY_TS(phy) && !(capflag & WLAN_RC_TS_FLAG))
- return 0;
- if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
- return 0;
- if (!ignore_cw && WLAN_RC_PHY_HT(phy))
- if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
- return 0;
- return 1;
-}
-
-static inline int
-ath_rc_get_lower_rix(struct ath_rate_priv *ath_rc_priv,
- u8 cur_valid_txrate, u8 *next_idx)
-{
- int8_t i;
-
- for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
- if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
- *next_idx = ath_rc_priv->valid_rate_index[i-1];
- return 1;
- }
- }
-
- return 0;
-}
-
-static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv)
-{
- const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
- u8 i, hi = 0;
-
- for (i = 0; i < rate_table->rate_cnt; i++) {
- if (rate_table->info[i].rate_flags & RC_LEGACY) {
- u32 phy = rate_table->info[i].phy;
- u8 valid_rate_count = 0;
-
- if (!ath_rc_valid_phyrate(phy, ath_rc_priv->ht_cap, 0))
- continue;
-
- valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
-
- ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
- ath_rc_priv->valid_phy_ratecnt[phy] += 1;
- ath_rc_priv->valid_rate_index[i] = true;
- hi = i;
- }
- }
-
- return hi;
-}
-
-static inline bool ath_rc_check_legacy(u8 rate, u8 dot11rate, u16 rate_flags,
- u32 phy, u32 capflag)
-{
- if (rate != dot11rate || WLAN_RC_PHY_HT(phy))
- return false;
-
- if ((rate_flags & WLAN_RC_CAP_MODE(capflag)) != WLAN_RC_CAP_MODE(capflag))
- return false;
-
- if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag)))
- return false;
-
- return true;
-}
-
-static inline bool ath_rc_check_ht(u8 rate, u8 dot11rate, u16 rate_flags,
- u32 phy, u32 capflag)
-{
- if (rate != dot11rate || !WLAN_RC_PHY_HT(phy))
- return false;
-
- if (!WLAN_RC_PHY_HT_VALID(rate_flags, capflag))
- return false;
-
- if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag)))
- return false;
-
- return true;
-}
-
-static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, bool legacy)
-{
- const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
- struct ath_rateset *rateset;
- u32 phy, capflag = ath_rc_priv->ht_cap;
- u16 rate_flags;
- u8 i, j, hi = 0, rate, dot11rate, valid_rate_count;
-
- if (legacy)
- rateset = &ath_rc_priv->neg_rates;
- else
- rateset = &ath_rc_priv->neg_ht_rates;
-
- for (i = 0; i < rateset->rs_nrates; i++) {
- for (j = 0; j < rate_table->rate_cnt; j++) {
- phy = rate_table->info[j].phy;
- rate_flags = rate_table->info[j].rate_flags;
- rate = rateset->rs_rates[i];
- dot11rate = rate_table->info[j].dot11rate;
-
- if (legacy &&
- !ath_rc_check_legacy(rate, dot11rate,
- rate_flags, phy, capflag))
- continue;
-
- if (!legacy &&
- !ath_rc_check_ht(rate, dot11rate,
- rate_flags, phy, capflag))
- continue;
-
- if (!ath_rc_valid_phyrate(phy, capflag, 0))
- continue;
-
- valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
- ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j;
- ath_rc_priv->valid_phy_ratecnt[phy] += 1;
- ath_rc_priv->valid_rate_index[j] = true;
- hi = max(hi, j);
- }
- }
-
- return hi;
-}
-
-static u8 ath_rc_get_highest_rix(struct ath_rate_priv *ath_rc_priv,
- int *is_probing)
-{
- const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
- u32 best_thruput, this_thruput, now_msec;
- u8 rate, next_rate, best_rate, maxindex, minindex;
- int8_t index = 0;
-
- now_msec = jiffies_to_msecs(jiffies);
- *is_probing = 0;
- best_thruput = 0;
- maxindex = ath_rc_priv->max_valid_rate-1;
- minindex = 0;
- best_rate = minindex;
-
- /*
- * Try the higher rate first. It will reduce memory moving time
- * if we have very good channel characteristics.
- */
- for (index = maxindex; index >= minindex ; index--) {
- u8 per_thres;
-
- rate = ath_rc_priv->valid_rate_index[index];
- if (rate > ath_rc_priv->rate_max_phy)
- continue;
-
- /*
- * For TCP the average collision rate is around 11%,
- * so we ignore PERs less than this. This is to
- * prevent the rate we are currently using (whose
- * PER might be in the 10-15 range because of TCP
- * collisions) looking worse than the next lower
- * rate whose PER has decayed close to 0. If we
- * used to next lower rate, its PER would grow to
- * 10-15 and we would be worse off then staying
- * at the current rate.
- */
- per_thres = ath_rc_priv->per[rate];
- if (per_thres < 12)
- per_thres = 12;
-
- this_thruput = rate_table->info[rate].user_ratekbps *
- (100 - per_thres);
-
- if (best_thruput <= this_thruput) {
- best_thruput = this_thruput;
- best_rate = rate;
- }
- }
-
- rate = best_rate;
-
- /*
- * Must check the actual rate (ratekbps) to account for
- * non-monoticity of 11g's rate table
- */
-
- if (rate >= ath_rc_priv->rate_max_phy) {
- rate = ath_rc_priv->rate_max_phy;
-
- /* Probe the next allowed phy state */
- if (ath_rc_get_nextvalid_txrate(rate_table,
- ath_rc_priv, rate, &next_rate) &&
- (now_msec - ath_rc_priv->probe_time >
- rate_table->probe_interval) &&
- (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
- rate = next_rate;
- ath_rc_priv->probe_rate = rate;
- ath_rc_priv->probe_time = now_msec;
- ath_rc_priv->hw_maxretry_pktcnt = 0;
- *is_probing = 1;
- }
- }
-
- if (rate > (ath_rc_priv->rate_table_size - 1))
- rate = ath_rc_priv->rate_table_size - 1;
-
- if (RC_TS_ONLY(rate_table->info[rate].rate_flags) &&
- (ath_rc_priv->ht_cap & WLAN_RC_TS_FLAG))
- return rate;
-
- if (RC_DS_OR_LATER(rate_table->info[rate].rate_flags) &&
- (ath_rc_priv->ht_cap & (WLAN_RC_DS_FLAG | WLAN_RC_TS_FLAG)))
- return rate;
-
- if (RC_SS_OR_LEGACY(rate_table->info[rate].rate_flags))
- return rate;
-
- /* This should not happen */
- WARN_ON_ONCE(1);
-
- rate = ath_rc_priv->valid_rate_index[0];
-
- return rate;
-}
-
-static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,
- struct ieee80211_tx_rate *rate,
- struct ieee80211_tx_rate_control *txrc,
- u8 tries, u8 rix, int rtsctsenable)
-{
- rate->count = tries;
- rate->idx = rate_table->info[rix].ratecode;
-
- if (txrc->rts || rtsctsenable)
- rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
-
- if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) {
- rate->flags |= IEEE80211_TX_RC_MCS;
- if (WLAN_RC_PHY_40(rate_table->info[rix].phy) &&
- conf_is_ht40(&txrc->hw->conf))
- rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
- if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
- rate->flags |= IEEE80211_TX_RC_SHORT_GI;
- }
-}
-
-static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
- const struct ath_rate_table *rate_table,
- struct ieee80211_tx_info *tx_info)
-{
- struct ieee80211_bss_conf *bss_conf;
-
- if (!tx_info->control.vif)
- return;
- /*
- * For legacy frames, mac80211 takes care of CTS protection.
- */
- if (!(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS))
- return;
-
- bss_conf = &tx_info->control.vif->bss_conf;
-
- if (!bss_conf->basic_rates)
- return;
-
- /*
- * For now, use the lowest allowed basic rate for HT frames.
- */
- tx_info->control.rts_cts_rate_idx = __ffs(bss_conf->basic_rates);
-}
-
-static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
- struct ieee80211_tx_rate_control *txrc)
-{
- struct ath_softc *sc = priv;
- struct ath_rate_priv *ath_rc_priv = priv_sta;
- const struct ath_rate_table *rate_table;
- struct sk_buff *skb = txrc->skb;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_rate *rates = tx_info->control.rates;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- __le16 fc = hdr->frame_control;
- u8 try_per_rate, i = 0, rix;
- int is_probe = 0;
-
- if (rate_control_send_low(sta, priv_sta, txrc))
- return;
-
- /*
- * For Multi Rate Retry we use a different number of
- * retry attempt counts. This ends up looking like this:
- *
- * MRR[0] = 4
- * MRR[1] = 4
- * MRR[2] = 4
- * MRR[3] = 8
- *
- */
- try_per_rate = 4;
-
- rate_table = ath_rc_priv->rate_table;
- rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe);
-
- if (conf_is_ht(&sc->hw->conf) &&
- (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
- tx_info->flags |= IEEE80211_TX_CTL_LDPC;
-
- if (conf_is_ht(&sc->hw->conf) &&
- (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
- tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT);
-
- if (is_probe) {
- /*
- * Set one try for probe rates. For the
- * probes don't enable RTS.
- */
- ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
- 1, rix, 0);
- /*
- * Get the next tried/allowed rate.
- * No RTS for the next series after the probe rate.
- */
- ath_rc_get_lower_rix(ath_rc_priv, rix, &rix);
- ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
- try_per_rate, rix, 0);
-
- tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
- } else {
- /*
- * Set the chosen rate. No RTS for first series entry.
- */
- ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
- try_per_rate, rix, 0);
- }
-
- for ( ; i < 4; i++) {
- /*
- * Use twice the number of tries for the last MRR segment.
- */
- if (i + 1 == 4)
- try_per_rate = 8;
-
- ath_rc_get_lower_rix(ath_rc_priv, rix, &rix);
-
- /*
- * All other rates in the series have RTS enabled.
- */
- ath_rc_rate_set_series(rate_table, &rates[i], txrc,
- try_per_rate, rix, 1);
- }
-
- /*
- * NB:Change rate series to enable aggregation when operating
- * at lower MCS rates. When first rate in series is MCS2
- * in HT40 @ 2.4GHz, series should look like:
- *
- * {MCS2, MCS1, MCS0, MCS0}.
- *
- * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
- * look like:
- *
- * {MCS3, MCS2, MCS1, MCS1}
- *
- * So, set fourth rate in series to be same as third one for
- * above conditions.
- */
- if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
- (conf_is_ht(&sc->hw->conf))) {
- u8 dot11rate = rate_table->info[rix].dot11rate;
- u8 phy = rate_table->info[rix].phy;
- if (i == 4 &&
- ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
- (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
- rates[3].idx = rates[2].idx;
- rates[3].flags = rates[2].flags;
- }
- }
-
- /*
- * Force hardware to use computed duration for next
- * fragment by disabling multi-rate retry, which
- * updates duration based on the multi-rate duration table.
- *
- * FIXME: Fix duration
- */
- if (ieee80211_has_morefrags(fc) ||
- (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
- rates[1].count = rates[2].count = rates[3].count = 0;
- rates[1].idx = rates[2].idx = rates[3].idx = 0;
- rates[0].count = ATH_TXMAXTRY;
- }
-
- ath_rc_rate_set_rtscts(sc, rate_table, tx_info);
-}
-
-static void ath_rc_update_per(struct ath_softc *sc,
- const struct ath_rate_table *rate_table,
- struct ath_rate_priv *ath_rc_priv,
- struct ieee80211_tx_info *tx_info,
- int tx_rate, int xretries, int retries,
- u32 now_msec)
-{
- int count, n_bad_frames;
- u8 last_per;
- static const u32 nretry_to_per_lookup[10] = {
- 100 * 0 / 1,
- 100 * 1 / 4,
- 100 * 1 / 2,
- 100 * 3 / 4,
- 100 * 4 / 5,
- 100 * 5 / 6,
- 100 * 6 / 7,
- 100 * 7 / 8,
- 100 * 8 / 9,
- 100 * 9 / 10
- };
-
- last_per = ath_rc_priv->per[tx_rate];
- n_bad_frames = tx_info->status.ampdu_len - tx_info->status.ampdu_ack_len;
-
- if (xretries) {
- if (xretries == 1) {
- ath_rc_priv->per[tx_rate] += 30;
- if (ath_rc_priv->per[tx_rate] > 100)
- ath_rc_priv->per[tx_rate] = 100;
- } else {
- /* xretries == 2 */
- count = ARRAY_SIZE(nretry_to_per_lookup);
- if (retries >= count)
- retries = count - 1;
-
- /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
- ath_rc_priv->per[tx_rate] =
- (u8)(last_per - (last_per >> 3) + (100 >> 3));
- }
-
- /* xretries == 1 or 2 */
-
- if (ath_rc_priv->probe_rate == tx_rate)
- ath_rc_priv->probe_rate = 0;
-
- } else { /* xretries == 0 */
- count = ARRAY_SIZE(nretry_to_per_lookup);
- if (retries >= count)
- retries = count - 1;
-
- if (n_bad_frames) {
- /* new_PER = 7/8*old_PER + 1/8*(currentPER)
- * Assuming that n_frames is not 0. The current PER
- * from the retries is 100 * retries / (retries+1),
- * since the first retries attempts failed, and the
- * next one worked. For the one that worked,
- * n_bad_frames subframes out of n_frames wored,
- * so the PER for that part is
- * 100 * n_bad_frames / n_frames, and it contributes
- * 100 * n_bad_frames / (n_frames * (retries+1)) to
- * the above PER. The expression below is a
- * simplified version of the sum of these two terms.
- */
- if (tx_info->status.ampdu_len > 0) {
- int n_frames, n_bad_tries;
- u8 cur_per, new_per;
-
- n_bad_tries = retries * tx_info->status.ampdu_len +
- n_bad_frames;
- n_frames = tx_info->status.ampdu_len * (retries + 1);
- cur_per = (100 * n_bad_tries / n_frames) >> 3;
- new_per = (u8)(last_per - (last_per >> 3) + cur_per);
- ath_rc_priv->per[tx_rate] = new_per;
- }
- } else {
- ath_rc_priv->per[tx_rate] =
- (u8)(last_per - (last_per >> 3) +
- (nretry_to_per_lookup[retries] >> 3));
- }
-
-
- /*
- * If we got at most one retry then increase the max rate if
- * this was a probe. Otherwise, ignore the probe.
- */
- if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
- if (retries > 0 || 2 * n_bad_frames > tx_info->status.ampdu_len) {
- /*
- * Since we probed with just a single attempt,
- * any retries means the probe failed. Also,
- * if the attempt worked, but more than half
- * the subframes were bad then also consider
- * the probe a failure.
- */
- ath_rc_priv->probe_rate = 0;
- } else {
- u8 probe_rate = 0;
-
- ath_rc_priv->rate_max_phy =
- ath_rc_priv->probe_rate;
- probe_rate = ath_rc_priv->probe_rate;
-
- if (ath_rc_priv->per[probe_rate] > 30)
- ath_rc_priv->per[probe_rate] = 20;
-
- ath_rc_priv->probe_rate = 0;
-
- /*
- * Since this probe succeeded, we allow the next
- * probe twice as soon. This allows the maxRate
- * to move up faster if the probes are
- * successful.
- */
- ath_rc_priv->probe_time =
- now_msec - rate_table->probe_interval / 2;
- }
- }
-
- if (retries > 0) {
- /*
- * Don't update anything. We don't know if
- * this was because of collisions or poor signal.
- */
- ath_rc_priv->hw_maxretry_pktcnt = 0;
- } else {
- /*
- * It worked with no retries. First ignore bogus (small)
- * rssi_ack values.
- */
- if (tx_rate == ath_rc_priv->rate_max_phy &&
- ath_rc_priv->hw_maxretry_pktcnt < 255) {
- ath_rc_priv->hw_maxretry_pktcnt++;
- }
-
- }
- }
-}
-
-static void ath_rc_update_ht(struct ath_softc *sc,
- struct ath_rate_priv *ath_rc_priv,
- struct ieee80211_tx_info *tx_info,
- int tx_rate, int xretries, int retries)
-{
- u32 now_msec = jiffies_to_msecs(jiffies);
- int rate;
- u8 last_per;
- const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
- int size = ath_rc_priv->rate_table_size;
-
- if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
- return;
-
- last_per = ath_rc_priv->per[tx_rate];
-
- /* Update PER first */
- ath_rc_update_per(sc, rate_table, ath_rc_priv,
- tx_info, tx_rate, xretries,
- retries, now_msec);
-
- /*
- * If this rate looks bad (high PER) then stop using it for
- * a while (except if we are probing).
- */
- if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 &&
- rate_table->info[tx_rate].ratekbps <=
- rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
- ath_rc_get_lower_rix(ath_rc_priv, (u8)tx_rate,
- &ath_rc_priv->rate_max_phy);
-
- /* Don't probe for a little while. */
- ath_rc_priv->probe_time = now_msec;
- }
-
- /* Make sure the rates below this have lower PER */
- /* Monotonicity is kept only for rates below the current rate. */
- if (ath_rc_priv->per[tx_rate] < last_per) {
- for (rate = tx_rate - 1; rate >= 0; rate--) {
-
- if (ath_rc_priv->per[rate] >
- ath_rc_priv->per[rate+1]) {
- ath_rc_priv->per[rate] =
- ath_rc_priv->per[rate+1];
- }
- }
- }
-
- /* Maintain monotonicity for rates above the current rate */
- for (rate = tx_rate; rate < size - 1; rate++) {
- if (ath_rc_priv->per[rate+1] <
- ath_rc_priv->per[rate])
- ath_rc_priv->per[rate+1] =
- ath_rc_priv->per[rate];
- }
-
- /* Every so often, we reduce the thresholds
- * and PER (different for CCK and OFDM). */
- if (now_msec - ath_rc_priv->per_down_time >=
- rate_table->probe_interval) {
- for (rate = 0; rate < size; rate++) {
- ath_rc_priv->per[rate] =
- 7 * ath_rc_priv->per[rate] / 8;
- }
-
- ath_rc_priv->per_down_time = now_msec;
- }
-
- ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries,
- ath_rc_priv->per[tx_rate]);
-
-}
-
-static void ath_rc_tx_status(struct ath_softc *sc,
- struct ath_rate_priv *ath_rc_priv,
- struct sk_buff *skb)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_rate *rates = tx_info->status.rates;
- struct ieee80211_tx_rate *rate;
- int final_ts_idx = 0, xretries = 0, long_retry = 0;
- u8 flags;
- u32 i = 0, rix;
-
- for (i = 0; i < sc->hw->max_rates; i++) {
- rate = &tx_info->status.rates[i];
- if (rate->idx < 0 || !rate->count)
- break;
-
- final_ts_idx = i;
- long_retry = rate->count - 1;
- }
-
- if (!(tx_info->flags & IEEE80211_TX_STAT_ACK))
- xretries = 1;
-
- /*
- * If the first rate is not the final index, there
- * are intermediate rate failures to be processed.
- */
- if (final_ts_idx != 0) {
- for (i = 0; i < final_ts_idx ; i++) {
- if (rates[i].count != 0 && (rates[i].idx >= 0)) {
- flags = rates[i].flags;
-
- /* If HT40 and we have switched mode from
- * 40 to 20 => don't update */
-
- if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
- !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
- return;
-
- rix = ath_rc_get_rateindex(ath_rc_priv, &rates[i]);
- ath_rc_update_ht(sc, ath_rc_priv, tx_info,
- rix, xretries ? 1 : 2,
- rates[i].count);
- }
- }
- }
-
- flags = rates[final_ts_idx].flags;
-
- /* If HT40 and we have switched mode from 40 to 20 => don't update */
- if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
- !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
- return;
-
- rix = ath_rc_get_rateindex(ath_rc_priv, &rates[final_ts_idx]);
- ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry);
- ath_debug_stat_rc(ath_rc_priv, rix);
-}
-
-static const
-struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
- enum ieee80211_band band,
- bool is_ht)
-{
- switch(band) {
- case IEEE80211_BAND_2GHZ:
- if (is_ht)
- return &ar5416_11ng_ratetable;
- return &ar5416_11g_ratetable;
- case IEEE80211_BAND_5GHZ:
- if (is_ht)
- return &ar5416_11na_ratetable;
- return &ar5416_11a_ratetable;
- default:
- return NULL;
- }
-}
-
-static void ath_rc_init(struct ath_softc *sc,
- struct ath_rate_priv *ath_rc_priv)
-{
- const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
- struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- u8 i, j, k, hi = 0, hthi = 0;
-
- ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
-
- for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
- ath_rc_priv->per[i] = 0;
- ath_rc_priv->valid_rate_index[i] = 0;
- }
-
- for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
- for (j = 0; j < RATE_TABLE_SIZE; j++)
- ath_rc_priv->valid_phy_rateidx[i][j] = 0;
- ath_rc_priv->valid_phy_ratecnt[i] = 0;
- }
-
- if (!rateset->rs_nrates) {
- hi = ath_rc_init_validrates(ath_rc_priv);
- } else {
- hi = ath_rc_setvalid_rates(ath_rc_priv, true);
-
- if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG)
- hthi = ath_rc_setvalid_rates(ath_rc_priv, false);
-
- hi = max(hi, hthi);
- }
-
- ath_rc_priv->rate_table_size = hi + 1;
- ath_rc_priv->rate_max_phy = 0;
- WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE);
-
- for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
- for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
- ath_rc_priv->valid_rate_index[k++] =
- ath_rc_priv->valid_phy_rateidx[i][j];
- }
-
- if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) ||
- !ath_rc_priv->valid_phy_ratecnt[i])
- continue;
-
- ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
- }
- WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE);
- WARN_ON(k > RATE_TABLE_SIZE);
-
- ath_rc_priv->max_valid_rate = k;
- ath_rc_sort_validrates(ath_rc_priv);
- ath_rc_priv->rate_max_phy = (k > 4) ?
- ath_rc_priv->valid_rate_index[k-4] :
- ath_rc_priv->valid_rate_index[k-1];
-
- ath_dbg(common, CONFIG, "RC Initialized with capabilities: 0x%x\n",
- ath_rc_priv->ht_cap);
-}
-
-static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta)
-{
- u8 caps = 0;
-
- if (sta->ht_cap.ht_supported) {
- caps = WLAN_RC_HT_FLAG;
- if (sta->ht_cap.mcs.rx_mask[1] && sta->ht_cap.mcs.rx_mask[2])
- caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG;
- else if (sta->ht_cap.mcs.rx_mask[1])
- caps |= WLAN_RC_DS_FLAG;
- if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
- caps |= WLAN_RC_40_FLAG;
- if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
- caps |= WLAN_RC_SGI_FLAG;
- } else {
- if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
- caps |= WLAN_RC_SGI_FLAG;
- }
- }
-
- return caps;
-}
-
-static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta,
- u8 tidno)
-{
- struct ath_node *an = (struct ath_node *)sta->drv_priv;
- struct ath_atx_tid *txtid;
-
- if (!sta->ht_cap.ht_supported)
- return false;
-
- txtid = ATH_AN_2_TID(an, tidno);
-
- if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
- return true;
- return false;
-}
-
-
-/***********************************/
-/* mac80211 Rate Control callbacks */
-/***********************************/
-
-static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta, void *priv_sta,
- struct sk_buff *skb)
-{
- struct ath_softc *sc = priv;
- struct ath_rate_priv *ath_rc_priv = priv_sta;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- __le16 fc = hdr->frame_control;
-
- if (!priv_sta || !ieee80211_is_data(fc))
- return;
-
- /* This packet was aggregated but doesn't carry status info */
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
- !(tx_info->flags & IEEE80211_TX_STAT_AMPDU))
- return;
-
- if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
- return;
-
- ath_rc_tx_status(sc, ath_rc_priv, skb);
-
- /* Check if aggregation has to be enabled for this tid */
- if (conf_is_ht(&sc->hw->conf) &&
- !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
- if (ieee80211_is_data_qos(fc) &&
- skb_get_queue_mapping(skb) != IEEE80211_AC_VO) {
- u8 *qc, tid;
-
- qc = ieee80211_get_qos_ctl(hdr);
- tid = qc[0] & 0xf;
-
- if(ath_tx_aggr_check(sc, sta, tid))
- ieee80211_start_tx_ba_session(sta, tid, 0);
- }
- }
-}
-
-static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta, void *priv_sta)
-{
- struct ath_softc *sc = priv;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_rate_priv *ath_rc_priv = priv_sta;
- int i, j = 0;
-
- for (i = 0; i < sband->n_bitrates; i++) {
- if (sta->supp_rates[sband->band] & BIT(i)) {
- ath_rc_priv->neg_rates.rs_rates[j]
- = (sband->bitrates[i].bitrate * 2) / 10;
- j++;
- }
- }
- ath_rc_priv->neg_rates.rs_nrates = j;
-
- if (sta->ht_cap.ht_supported) {
- for (i = 0, j = 0; i < 77; i++) {
- if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
- ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
- if (j == ATH_RATE_MAX)
- break;
- }
- ath_rc_priv->neg_ht_rates.rs_nrates = j;
- }
-
- ath_rc_priv->rate_table = ath_choose_rate_table(sc, sband->band,
- sta->ht_cap.ht_supported);
- if (!ath_rc_priv->rate_table) {
- ath_err(common, "No rate table chosen\n");
- return;
- }
-
- ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta);
- ath_rc_init(sc, priv_sta);
-}
-
-static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta, void *priv_sta,
- u32 changed)
-{
- struct ath_softc *sc = priv;
- struct ath_rate_priv *ath_rc_priv = priv_sta;
-
- if (changed & IEEE80211_RC_BW_CHANGED) {
- ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta);
- ath_rc_init(sc, priv_sta);
-
- ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
- "Operating HT Bandwidth changed to: %d\n",
- sc->hw->conf.channel_type);
- }
-}
-
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
-
-void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
-{
- struct ath_rc_stats *stats;
-
- stats = &rc->rcstats[final_rate];
- stats->success++;
-}
-
-void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
- int xretries, int retries, u8 per)
-{
- struct ath_rc_stats *stats = &rc->rcstats[rix];
-
- stats->xretries += xretries;
- stats->retries += retries;
- stats->per = per;
-}
-
-static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath_rate_priv *rc = file->private_data;
- char *buf;
- unsigned int len = 0, max;
- int rix;
- ssize_t retval;
-
- if (rc->rate_table == NULL)
- return 0;
-
- max = 80 + rc->rate_table_size * 1024 + 1;
- buf = kmalloc(max, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- len += sprintf(buf, "%6s %6s %6s "
- "%10s %10s %10s %10s\n",
- "HT", "MCS", "Rate",
- "Success", "Retries", "XRetries", "PER");
-
- for (rix = 0; rix < rc->max_valid_rate; rix++) {
- u8 i = rc->valid_rate_index[rix];
- u32 ratekbps = rc->rate_table->info[i].ratekbps;
- struct ath_rc_stats *stats = &rc->rcstats[i];
- char mcs[5];
- char htmode[5];
- int used_mcs = 0, used_htmode = 0;
-
- if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) {
- used_mcs = snprintf(mcs, 5, "%d",
- rc->rate_table->info[i].ratecode);
-
- if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy))
- used_htmode = snprintf(htmode, 5, "HT40");
- else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy))
- used_htmode = snprintf(htmode, 5, "HT20");
- else
- used_htmode = snprintf(htmode, 5, "????");
- }
-
- mcs[used_mcs] = '\0';
- htmode[used_htmode] = '\0';
-
- len += snprintf(buf + len, max - len,
- "%6s %6s %3u.%d: "
- "%10u %10u %10u %10u\n",
- htmode,
- mcs,
- ratekbps / 1000,
- (ratekbps % 1000) / 100,
- stats->success,
- stats->retries,
- stats->xretries,
- stats->per);
- }
-
- if (len > max)
- len = max;
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
- return retval;
-}
-
-static const struct file_operations fops_rcstat = {
- .read = read_file_rcstat,
- .open = simple_open,
- .owner = THIS_MODULE
-};
-
-static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
- struct dentry *dir)
-{
- struct ath_rate_priv *rc = priv_sta;
- rc->debugfs_rcstats = debugfs_create_file("rc_stats", S_IRUGO,
- dir, rc, &fops_rcstat);
-}
-
-static void ath_rate_remove_sta_debugfs(void *priv, void *priv_sta)
-{
- struct ath_rate_priv *rc = priv_sta;
- debugfs_remove(rc->debugfs_rcstats);
-}
-
-#endif /* CONFIG_MAC80211_DEBUGFS && CONFIG_ATH9K_DEBUGFS */
-
-static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
-{
- return hw->priv;
-}
-
-static void ath_rate_free(void *priv)
-{
- return;
-}
-
-static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
-{
- struct ath_softc *sc = priv;
- struct ath_rate_priv *rate_priv;
-
- rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
- if (!rate_priv) {
- ath_err(ath9k_hw_common(sc->sc_ah),
- "Unable to allocate private rc structure\n");
- return NULL;
- }
-
- return rate_priv;
-}
-
-static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
- void *priv_sta)
-{
- struct ath_rate_priv *rate_priv = priv_sta;
- kfree(rate_priv);
-}
-
-static struct rate_control_ops ath_rate_ops = {
- .module = NULL,
- .name = "ath9k_rate_control",
- .tx_status = ath_tx_status,
- .get_rate = ath_get_rate,
- .rate_init = ath_rate_init,
- .rate_update = ath_rate_update,
- .alloc = ath_rate_alloc,
- .free = ath_rate_free,
- .alloc_sta = ath_rate_alloc_sta,
- .free_sta = ath_rate_free_sta,
-
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
- .add_sta_debugfs = ath_rate_add_sta_debugfs,
- .remove_sta_debugfs = ath_rate_remove_sta_debugfs,
-#endif
-};
-
-int ath_rate_control_register(void)
-{
- return ieee80211_rate_control_register(&ath_rate_ops);
-}
-
-void ath_rate_control_unregister(void)
-{
- ieee80211_rate_control_unregister(&ath_rate_ops);
-}
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
deleted file mode 100644
index 267dbfc..0000000
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2004 Sam Leffler, Errno Consulting
- * Copyright (c) 2004 Video54 Technologies, Inc.
- * Copyright (c) 2008-2011 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef RC_H
-#define RC_H
-
-#include "hw.h"
-
-struct ath_softc;
-
-#define ATH_RATE_MAX 30
-#define RATE_TABLE_SIZE 72
-
-#define RC_INVALID 0x0000
-#define RC_LEGACY 0x0001
-#define RC_SS 0x0002
-#define RC_DS 0x0004
-#define RC_TS 0x0008
-#define RC_HT_20 0x0010
-#define RC_HT_40 0x0020
-
-#define RC_STREAM_MASK 0xe
-#define RC_DS_OR_LATER(f) ((((f) & RC_STREAM_MASK) == RC_DS) || \
- (((f) & RC_STREAM_MASK) == (RC_DS | RC_TS)))
-#define RC_TS_ONLY(f) (((f) & RC_STREAM_MASK) == RC_TS)
-#define RC_SS_OR_LEGACY(f) ((f) & (RC_SS | RC_LEGACY))
-
-#define RC_HT_2040 (RC_HT_20 | RC_HT_40)
-#define RC_ALL_STREAM (RC_SS | RC_DS | RC_TS)
-#define RC_L_SD (RC_LEGACY | RC_SS | RC_DS)
-#define RC_L_SDT (RC_LEGACY | RC_SS | RC_DS | RC_TS)
-#define RC_HT_S_20 (RC_HT_20 | RC_SS)
-#define RC_HT_D_20 (RC_HT_20 | RC_DS)
-#define RC_HT_T_20 (RC_HT_20 | RC_TS)
-#define RC_HT_S_40 (RC_HT_40 | RC_SS)
-#define RC_HT_D_40 (RC_HT_40 | RC_DS)
-#define RC_HT_T_40 (RC_HT_40 | RC_TS)
-
-#define RC_HT_SD_20 (RC_HT_20 | RC_SS | RC_DS)
-#define RC_HT_DT_20 (RC_HT_20 | RC_DS | RC_TS)
-#define RC_HT_SD_40 (RC_HT_40 | RC_SS | RC_DS)
-#define RC_HT_DT_40 (RC_HT_40 | RC_DS | RC_TS)
-
-#define RC_HT_SD_2040 (RC_HT_2040 | RC_SS | RC_DS)
-#define RC_HT_SDT_2040 (RC_HT_2040 | RC_SS | RC_DS | RC_TS)
-
-#define RC_HT_SDT_20 (RC_HT_20 | RC_SS | RC_DS | RC_TS)
-#define RC_HT_SDT_40 (RC_HT_40 | RC_SS | RC_DS | RC_TS)
-
-#define RC_ALL (RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM)
-
-enum {
- WLAN_RC_PHY_OFDM,
- WLAN_RC_PHY_CCK,
- WLAN_RC_PHY_HT_20_SS,
- WLAN_RC_PHY_HT_20_DS,
- WLAN_RC_PHY_HT_20_TS,
- WLAN_RC_PHY_HT_40_SS,
- WLAN_RC_PHY_HT_40_DS,
- WLAN_RC_PHY_HT_40_TS,
- WLAN_RC_PHY_HT_20_SS_HGI,
- WLAN_RC_PHY_HT_20_DS_HGI,
- WLAN_RC_PHY_HT_20_TS_HGI,
- WLAN_RC_PHY_HT_40_SS_HGI,
- WLAN_RC_PHY_HT_40_DS_HGI,
- WLAN_RC_PHY_HT_40_TS_HGI,
- WLAN_RC_PHY_MAX
-};
-
-#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \
- || (_phy == WLAN_RC_PHY_HT_40_DS) \
- || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
-#define WLAN_RC_PHY_TS(_phy) ((_phy == WLAN_RC_PHY_HT_20_TS) \
- || (_phy == WLAN_RC_PHY_HT_40_TS) \
- || (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
-#define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \
- || (_phy == WLAN_RC_PHY_HT_20_DS) \
- || (_phy == WLAN_RC_PHY_HT_20_TS) \
- || (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_20_TS_HGI))
-#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \
- || (_phy == WLAN_RC_PHY_HT_40_DS) \
- || (_phy == WLAN_RC_PHY_HT_40_TS) \
- || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
-#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
-
-#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS)
-
-#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \
- ((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY))
-
-#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ? \
- (RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS)))
-
-/* Return TRUE if flag supports HT20 && client supports HT20 or
- * return TRUE if flag supports HT40 && client supports HT40.
- * This is used becos some rates overlap between HT20/HT40.
- */
-#define WLAN_RC_PHY_HT_VALID(flag, capflag) \
- (((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \
- ((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG)))
-
-#define WLAN_RC_DS_FLAG (0x01)
-#define WLAN_RC_TS_FLAG (0x02)
-#define WLAN_RC_40_FLAG (0x04)
-#define WLAN_RC_SGI_FLAG (0x08)
-#define WLAN_RC_HT_FLAG (0x10)
-
-/**
- * struct ath_rate_table - Rate Control table
- * @rate_cnt: total number of rates for the given wireless mode
- * @mcs_start: MCS rate index offset
- * @rate_flags: Rate Control flags
- * @phy: CCK/OFDM/HT20/HT40
- * @ratekbps: rate in Kbits per second
- * @user_ratekbps: user rate in Kbits per second
- * @ratecode: rate that goes into HW descriptors
- * @dot11rate: value that goes into supported
- * rates info element of MLME
- * @ctrl_rate: Index of next lower basic rate, used for duration computation
- * @cw40index: Index of rates having 40MHz channel width
- * @sgi_index: Index of rates having Short Guard Interval
- * @ht_index: high throughput rates having 40MHz channel width and
- * Short Guard Interval
- * @probe_interval: interval for rate control to probe for other rates
- * @initial_ratemax: initial ratemax value
- */
-struct ath_rate_table {
- int rate_cnt;
- int mcs_start;
- struct {
- u16 rate_flags;
- u8 phy;
- u32 ratekbps;
- u32 user_ratekbps;
- u8 ratecode;
- u8 dot11rate;
- } info[RATE_TABLE_SIZE];
- u32 probe_interval;
- u8 initial_ratemax;
-};
-
-struct ath_rateset {
- u8 rs_nrates;
- u8 rs_rates[ATH_RATE_MAX];
-};
-
-struct ath_rc_stats {
- u32 success;
- u32 retries;
- u32 xretries;
- u8 per;
-};
-
-/**
- * struct ath_rate_priv - Rate Control priv data
- * @state: RC state
- * @probe_rate: rate we are probing at
- * @probe_time: msec timestamp for last probe
- * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
- * @max_valid_rate: maximum number of valid rate
- * @per_down_time: msec timestamp for last PER down step
- * @valid_phy_ratecnt: valid rate count
- * @rate_max_phy: phy index for the max rate
- * @per: PER for every valid rate in %
- * @probe_interval: interval for ratectrl to probe for other rates
- * @ht_cap: HT capabilities
- * @neg_rates: Negotatied rates
- * @neg_ht_rates: Negotiated HT rates
- */
-struct ath_rate_priv {
- u8 rate_table_size;
- u8 probe_rate;
- u8 hw_maxretry_pktcnt;
- u8 max_valid_rate;
- u8 valid_rate_index[RATE_TABLE_SIZE];
- u8 ht_cap;
- u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
- u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
- u8 rate_max_phy;
- u8 per[RATE_TABLE_SIZE];
- u32 probe_time;
- u32 per_down_time;
- u32 probe_interval;
- struct ath_rateset neg_rates;
- struct ath_rateset neg_ht_rates;
- const struct ath_rate_table *rate_table;
-
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
- struct dentry *debugfs_rcstats;
- struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
-#endif
-};
-
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
-void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate);
-void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
- int xretries, int retries, u8 per);
-#else
-static inline void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
-{
-}
-static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
- int xretries, int retries, u8 per)
-{
-}
-#endif
-
-#ifdef CONFIG_ATH9K_RATE_CONTROL
-int ath_rate_control_register(void);
-void ath_rate_control_unregister(void);
-#else
-static inline int ath_rate_control_register(void)
-{
- return 0;
-}
-
-static inline void ath_rate_control_unregister(void)
-{
-}
-#endif
-
-#endif /* RC_H */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index feacaaf..b32fda8 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1008,8 +1008,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
info->rtscts_rate = fi->rtscts_rate;

for (i = 0; i < 4; i++) {
- bool is_40, is_sgi, is_sp;
- int phy;
+ bool is_40, is_sgi, is_sp, cck = false;

if (!rates[i].count || (rates[i].idx < 0))
continue;
@@ -1050,9 +1049,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
!(rate->flags & IEEE80211_RATE_ERP_G))
- phy = WLAN_RC_PHY_CCK;
- else
- phy = WLAN_RC_PHY_OFDM;
+ cck = true;

info->rates[i].Rate = rate->hw_value;
if (rate->hw_value_short) {
@@ -1069,7 +1066,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
ah->txchainmask, info->rates[i].Rate);

info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
- phy, rate->bitrate * 100, len, rix, is_sp);
+ cck, rate->bitrate * 100, len, rix, is_sp);
}

/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
--
1.8.0.2



2013-02-08 14:08:06

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Felix Fietkau wrote:
> I'm pretty sure it's because the algorithm isn't designed to handle more
> rates. It's a step-up/step-down type algorithm, and those typically only
> work with a sorted rateset, preferably duplicate free.
>
> Minstrel_ht selects rates in a different way that doesn't have the same
> limitations, so it can use the full rateset.

Makes sense.

Sujith

2013-02-08 16:38:37

by Paul Stewart

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Could you share some of the test results? I know with ChromeOS when
we switched to 3.4, the first thing that tipped us off to the fact
that we had inadvertently switch to minstrel was that our RvR
throughput values had dropped significantly. Has anyone done an RvR
comparison between minstrel and the ath9k internal rate control
lately?

--
Paul

On Fri, Feb 8, 2013 at 6:16 AM, Felix Fietkau <[email protected]> wrote:
> On 2013-02-08 3:08 PM, Sujith Manoharan wrote:
>> Felix Fietkau wrote:
>>> In many tests throughput with ath9k_rate_control has been shown to be
>>> worse than with minstrel_ht (the mac8021 default RC).
>>>
>>> This module also has some other problems, like starting to use the
>>> highest possible rate early in the connection, causing problems with
>>> reliability of connection/authentication attempts.
>>>
>>> It also has a much more limited search space, ignoring many potentially
>>> useful rates, caused by the design decision to operate on a sorted rate
>>> set with the assumption that higher rates are always more unreliable
>>> than lower rates. In some scenarios this assumption is not true, and
>>> this can cause it to fall back to a really bad rate.
>>>
>>> minstrel_ht has been tested extensively in AP and client mode by lots of
>>> users (mostly in the OpenWrt project, where it has been the default for
>>> years).
>>
>> I don't think managed mode would have received much testing in OpenWRT.
> I know quite a few people that use directional links with 4-addr
> AP/Station. I also know a few people that put up some devices that roam
> between multiple APs. Obviously it doesn't receive as much testing as AP
> mode, but there are some active users stress testing it.
>
> - Felix
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2013-02-08 16:53:56

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-02-08 5:38 PM, Paul Stewart wrote:
> Could you share some of the test results? I know with ChromeOS when
> we switched to 3.4, the first thing that tipped us off to the fact
> that we had inadvertently switch to minstrel was that our RvR
> throughput values had dropped significantly. Has anyone done an RvR
> comparison between minstrel and the ath9k internal rate control
> lately?
Are you sure it was minstrel_ht, or could it also have been minstrel
(the legacy version)? I don't have any recent RvR test results, however
on every single link that I tested both rate control modules on (leaving
everything else unchanged), minstrel_ht got slightly better results.
Additionally, I occasionally get asked for help on debugging low
throughput issues, and many of the people asking me have reported that
simply switching to minstrel_ht fixed these issues in their tests.

I would also like to see some real RvR tests comparing both, preferably
before this gets merged, which is why I sent it as RFC.

- Felix

2013-02-28 05:10:20

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Felix Fietkau wrote:
> What was the distance and what was the rate used?

The station was about a meter away from the AP. I don't have the rcstats,
debugfs was compiled out. I'll rerun the test and post the results.

Sujith

2013-02-28 03:55:49

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Felix Fietkau wrote:
> I don't see the point in keeping that algorithm around. It has known
> design flaws that make it perform poorly in several scenarios, and
> fixing some of the flaws require basically rewriting it.

I ran some comparison throughput tests between minstrel_ht and ath9k RC
and minstrel showed lower numbers (~10Mbps difference). This is in a clean
environment (OTA). IMO, we can switch the default to minstrel_ht, but keep
the ath9k RC until the perf. gap is fixed. I think this was Google's concern too,
a drop in the average throughput. This was in the STA->AP direction.

In the AP->STA direction (AP: DB120, STA: AR9280), the numbers were really low.
The highest that I could see was ~165 Mbps, while with WNDR3700 (stock FW), the
average throughput was ~185 Mbps and an occasional high of 190 and above.

Sujith

2013-02-08 14:04:21

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-02-08 2:30 PM, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> In many tests throughput with ath9k_rate_control has been shown to be
>> worse than with minstrel_ht (the mac8021 default RC).
>>
>> This module also has some other problems, like starting to use the
>> highest possible rate early in the connection, causing problems with
>> reliability of connection/authentication attempts.
>>
>> It also has a much more limited search space, ignoring many potentially
>> useful rates, caused by the design decision to operate on a sorted rate
>> set with the assumption that higher rates are always more unreliable
>> than lower rates. In some scenarios this assumption is not true, and
>> this can cause it to fall back to a really bad rate.
>>
>> minstrel_ht has been tested extensively in AP and client mode by lots of
>> users (mostly in the OpenWrt project, where it has been the default for
>> years).
>>
>> The only advantage that ath9k_rate_control previously had over minstrel_ht
>> was the support for using CCK rates as fall back in case MCS rates got
>> too bad, but this has now also been taken care of.
>
> Various rates are marked as invalid in the ath9k rate control module. I don't
> know all the reasons, but the recommendation to disable certain rates came from
> the internal algorithms team. How will this be handled ?
I'm pretty sure it's because the algorithm isn't designed to handle more
rates. It's a step-up/step-down type algorithm, and those typically only
work with a sorted rateset, preferably duplicate free.

Minstrel_ht selects rates in a different way that doesn't have the same
limitations, so it can use the full rateset.

- Felix


2013-02-08 14:09:40

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Felix Fietkau wrote:
> In many tests throughput with ath9k_rate_control has been shown to be
> worse than with minstrel_ht (the mac8021 default RC).
>
> This module also has some other problems, like starting to use the
> highest possible rate early in the connection, causing problems with
> reliability of connection/authentication attempts.
>
> It also has a much more limited search space, ignoring many potentially
> useful rates, caused by the design decision to operate on a sorted rate
> set with the assumption that higher rates are always more unreliable
> than lower rates. In some scenarios this assumption is not true, and
> this can cause it to fall back to a really bad rate.
>
> minstrel_ht has been tested extensively in AP and client mode by lots of
> users (mostly in the OpenWrt project, where it has been the default for
> years).

I don't think managed mode would have received much testing in OpenWRT.

> The only advantage that ath9k_rate_control previously had over minstrel_ht
> was the support for using CCK rates as fall back in case MCS rates got
> too bad, but this has now also been taken care of.
>
> Signed-off-by: Felix Fietkau <[email protected]>

Acked-by: Sujith Manoharan <[email protected]>

Sujith


2013-02-28 03:24:58

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-02-28 3:21 AM, Adrian Chadd wrote:
> Why don't we just move the ath9k rate control code to another mac80211
> rate control module, so it's available to other devices?
>
> It may not be a bad idea to keep it around as a reference and for
> people to do comparisons against. It just seems silly to have a rate
> control framework and then not use it..
I don't see the point in keeping that algorithm around. It has known
design flaws that make it perform poorly in several scenarios, and
fixing some of the flaws require basically rewriting it.

- Felix

2013-02-08 13:32:11

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Felix Fietkau wrote:
> In many tests throughput with ath9k_rate_control has been shown to be
> worse than with minstrel_ht (the mac8021 default RC).
>
> This module also has some other problems, like starting to use the
> highest possible rate early in the connection, causing problems with
> reliability of connection/authentication attempts.
>
> It also has a much more limited search space, ignoring many potentially
> useful rates, caused by the design decision to operate on a sorted rate
> set with the assumption that higher rates are always more unreliable
> than lower rates. In some scenarios this assumption is not true, and
> this can cause it to fall back to a really bad rate.
>
> minstrel_ht has been tested extensively in AP and client mode by lots of
> users (mostly in the OpenWrt project, where it has been the default for
> years).
>
> The only advantage that ath9k_rate_control previously had over minstrel_ht
> was the support for using CCK rates as fall back in case MCS rates got
> too bad, but this has now also been taken care of.

Various rates are marked as invalid in the ath9k rate control module. I don't
know all the reasons, but the recommendation to disable certain rates came from
the internal algorithms team. How will this be handled ?

Sujith

2013-02-28 11:47:27

by Bob Copeland

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On Thu, Feb 28, 2013 at 04:24:49AM +0100, Felix Fietkau wrote:
> On 2013-02-28 3:21 AM, Adrian Chadd wrote:
> > It may not be a bad idea to keep it around as a reference and for
> > people to do comparisons against. It just seems silly to have a rate
> > control framework and then not use it..
> I don't see the point in keeping that algorithm around. It has known
> design flaws that make it perform poorly in several scenarios, and
> fixing some of the flaws require basically rewriting it.

The same could be said of PID...

--
Bob Copeland %% http://www.bobcopeland.com

2013-02-28 19:07:52

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-02-28 7:53 PM, Adrian Chadd wrote:
> On 28 February 2013 05:09, Felix Fietkau <[email protected]> wrote:
>
>>> The same could be said of PID...
>> I agree, we should remove that one as well.
>
> One of the advantages of having multiple RC modules - even if they're
> not longer optimal - is to keep the API honest. :-)
>
> I still keep onoe/amrr working in FreeBSD's ath(4) driver, primarily
> to make sure that I don't change the API without thinking too much
> about what other rate control modules do, but also to provide a
> simpler example of how the API works.
In that case I'd rather keep PID than the ath9k rate control. The ath9k
rate control is a horrible example of how to use the rate control API,
and fixing that is a waste of time in my opinion.
By the way, minstrel and minstrel_ht are two mostly separate
implementations using the same API, except for the fact that minstrel_ht
falls back to minstrel for legacy clients. So we already do have
multiple examples here :)

> Personally, I'd like to see more examples of rate control modules in
> LInux/FreeBSD, especially ones that start demanding more 802.11 state
> (ie, air-time QoS.)
Do you have any good ideas on what state information would be useful for
a rate control to demand?

- Felix

2013-02-28 04:32:12

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-02-28 4:54 AM, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> I don't see the point in keeping that algorithm around. It has known
>> design flaws that make it perform poorly in several scenarios, and
>> fixing some of the flaws require basically rewriting it.
>
> I ran some comparison throughput tests between minstrel_ht and ath9k RC
> and minstrel showed lower numbers (~10Mbps difference). This is in a clean
> environment (OTA). IMO, we can switch the default to minstrel_ht, but keep
> the ath9k RC until the perf. gap is fixed. I think this was Google's concern too,
> a drop in the average throughput. This was in the STA->AP direction.
What was the distance and what was the rate used?

> In the AP->STA direction (AP: DB120, STA: AR9280), the numbers were really low.
> The highest that I could see was ~165 Mbps, while with WNDR3700 (stock FW), the
> average throughput was ~185 Mbps and an occasional high of 190 and above.
Comparing against stock FW (especially with different devices) is not
useful, it could be anything.

- Felix


2013-02-28 02:21:47

by Adrian Chadd

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Why don't we just move the ath9k rate control code to another mac80211
rate control module, so it's available to other devices?

It may not be a bad idea to keep it around as a reference and for
people to do comparisons against. It just seems silly to have a rate
control framework and then not use it..


Adrian

2013-02-28 13:09:38

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-02-28 12:47 PM, Bob Copeland wrote:
> On Thu, Feb 28, 2013 at 04:24:49AM +0100, Felix Fietkau wrote:
>> On 2013-02-28 3:21 AM, Adrian Chadd wrote:
>> > It may not be a bad idea to keep it around as a reference and for
>> > people to do comparisons against. It just seems silly to have a rate
>> > control framework and then not use it..
>> I don't see the point in keeping that algorithm around. It has known
>> design flaws that make it perform poorly in several scenarios, and
>> fixing some of the flaws require basically rewriting it.
>
> The same could be said of PID...
I agree, we should remove that one as well.

- Felix


2013-02-28 18:53:34

by Adrian Chadd

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 28 February 2013 05:09, Felix Fietkau <[email protected]> wrote:

>> The same could be said of PID...
> I agree, we should remove that one as well.

One of the advantages of having multiple RC modules - even if they're
not longer optimal - is to keep the API honest. :-)

I still keep onoe/amrr working in FreeBSD's ath(4) driver, primarily
to make sure that I don't change the API without thinking too much
about what other rate control modules do, but also to provide a
simpler example of how the API works.

Personally, I'd like to see more examples of rate control modules in
LInux/FreeBSD, especially ones that start demanding more 802.11 state
(ie, air-time QoS.)



Adrian

2013-02-08 14:16:09

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-02-08 3:08 PM, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> In many tests throughput with ath9k_rate_control has been shown to be
>> worse than with minstrel_ht (the mac8021 default RC).
>>
>> This module also has some other problems, like starting to use the
>> highest possible rate early in the connection, causing problems with
>> reliability of connection/authentication attempts.
>>
>> It also has a much more limited search space, ignoring many potentially
>> useful rates, caused by the design decision to operate on a sorted rate
>> set with the assumption that higher rates are always more unreliable
>> than lower rates. In some scenarios this assumption is not true, and
>> this can cause it to fall back to a really bad rate.
>>
>> minstrel_ht has been tested extensively in AP and client mode by lots of
>> users (mostly in the OpenWrt project, where it has been the default for
>> years).
>
> I don't think managed mode would have received much testing in OpenWRT.
I know quite a few people that use directional links with 4-addr
AP/Station. I also know a few people that put up some devices that roam
between multiple APs. Obviously it doesn't receive as much testing as AP
mode, but there are some active users stress testing it.

- Felix


2013-02-27 19:01:06

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On Fri, Feb 08, 2013 at 05:53:50PM +0100, Felix Fietkau wrote:
> On 2013-02-08 5:38 PM, Paul Stewart wrote:
> > Could you share some of the test results? I know with ChromeOS when
> > we switched to 3.4, the first thing that tipped us off to the fact
> > that we had inadvertently switch to minstrel was that our RvR
> > throughput values had dropped significantly. Has anyone done an RvR
> > comparison between minstrel and the ath9k internal rate control
> > lately?
> Are you sure it was minstrel_ht, or could it also have been minstrel
> (the legacy version)? I don't have any recent RvR test results, however
> on every single link that I tested both rate control modules on (leaving
> everything else unchanged), minstrel_ht got slightly better results.
> Additionally, I occasionally get asked for help on debugging low
> throughput issues, and many of the people asking me have reported that
> simply switching to minstrel_ht fixed these issues in their tests.
>
> I would also like to see some real RvR tests comparing both, preferably
> before this gets merged, which is why I sent it as RFC.

Paul, curious if you've run any tests?

Luis

2013-03-02 02:20:47

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Adrian Chadd wrote:
> (190mbit TCP on 2-stream? Damn. Looks like I have a little more
> optimisation to do in FreeBSD. I'm only hitting 160/170mbit TCP on
> AR9280<->AR9280 and AR9280<->AR9287. But I hit 220-240mbit UDP.)

I used a AR9462 card for this test. With AR9280/AR9287 I get abysmal
numbers with both rate control algorithms. Maybe something has regressed
in ath9k for the AR9002 family...

Sujith

2013-03-02 05:40:16

by Adrian Chadd

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 1 March 2013 18:19, Sujith Manoharan <[email protected]> wrote:
> Adrian Chadd wrote:
>> (190mbit TCP on 2-stream? Damn. Looks like I have a little more
>> optimisation to do in FreeBSD. I'm only hitting 160/170mbit TCP on
>> AR9280<->AR9280 and AR9280<->AR9287. But I hit 220-240mbit UDP.)
>
> I used a AR9462 card for this test. With AR9280/AR9287 I get abysmal
> numbers with both rate control algorithms. Maybe something has regressed
> in ath9k for the AR9002 family...

It's almost like we need some kind of lab space set aside for running
regression tests with all of the ath9k hardware ,dating back to
AR5416, with some automated testing rigs..

I have the hardware. Who wants to do it? :)



adrian

2013-03-01 11:18:03

by Mohammed Shafi

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Hi Felix,

On Fri, Mar 1, 2013 at 3:59 PM, Felix Fietkau <[email protected]> wrote:
> On 2013-03-01 11:22 AM, Adrian Chadd wrote:
>> On 1 March 2013 02:14, Felix Fietkau <[email protected]> wrote:
>>
>>>> Having access to schedule which peer and how much to send to each peer
>>>> would be nice. Stuff like "peer X only can have up to x ms in this WME
>>>> class this round", so you don't have a busy, close peer monopolising
>>>> the air. It also means you can start doing smart things with far away
>>>> peers who retransmit a lot - they're likely tying up a lot of airtime.
>>>>
>>>> None of this is new. It's just, you know, new to open source. :-)
>>
>>> In my opinion this doesn't really belong into a rate control module.
>>> There should be a tx scheduling API to take care of this. Before I
>>> implement something like this, I plan on exposing all per-station driver
>>> queues to mac80211. This is necessary for a few other things anyway,
>>> e.g. unifying software aggregation logic and fixing its buffer management.
>>
>> Sure, but then some more clever tricks end up being difficult to
>> implement. For example, knowing if a client is tying up too much
>> airtime at the given rate and whether to back them off for a bit. Or
>> to use smaller aggregation limits for certain clients because your'e
>> trying to be "fairer" when trying to keep latency low. That kind of
>> thing.
>>
>> I think "rate control" should likely be expanded to "tx scheduling" as
>> a whole, rather than sitting as a separate thing that just selects the
>> rate for a node who has already been chosen to transmit.
> Even with client airtime use, I still don't see how tx scheduling and
> rate control belong together. In my opinion, the rate selection should
> not be based on client airtime usage or the current load, as it can
> optimize for throughput/airtime ratio without it.
>

Algorithm folks and Engineers had spent considerable time on ath9k rate control.
Wouldn't be a great idea to remove it completely, We can have it optional.
With lot of throughput tests ran over internally and with the test
team verification,
it wouldn't be fair to throw it away.

--
thanks,
shafi

2013-03-01 10:09:34

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-03-01 2:23 AM, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> In that case I'd rather keep PID than the ath9k rate control. The ath9k
>> rate control is a horrible example of how to use the rate control API,
>> and fixing that is a waste of time in my opinion.
>
> I acked the earlier RFC patch to remove the ath9k RC as I assumed that minstrel_ht
> would perform adequately, if not better. But, there appear to be areas in which
> the numbers given by minstrel_ht are sub-optimal and which can be improved if we
> have something to compare it with. The ath9k RC code is crap, no doubt, but I'd
> prefer to have it for some time in the tree - we can switch the default RC to minstrel_ht
> by default.
Right, I will only submit this patch again once more performance tests
have been run. My own tests and tests of other people that I know of so
far have shown minstrel_ht to perform better than ath9k_rate_control,
whereas in your tests ath9k_rate_control seems to perform better. I'd
like to get some more details on your tests, e.g. raw numbers, rate
control stats, info on how much the throughput fluctuates, etc.

> Can you also explain how the ath9k RC uses the mac80211 API horribly ? The algorithm might be
> terribly implemented and the internal code nasty, but how does it violate the API ?
When I called it a horrible example, I was referring to the bad code
quality, not API violations. The API violations are only minor, there
are a few places left where the rate control code accesses struct ath_softc.

- Felix

2013-03-01 10:14:32

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-03-01 4:53 AM, Adrian Chadd wrote:
> On 28 February 2013 11:07, Felix Fietkau <[email protected]> wrote:
>
>>> Personally, I'd like to see more examples of rate control modules in
>>> LInux/FreeBSD, especially ones that start demanding more 802.11 state
>>> (ie, air-time QoS.)
>
>> Do you have any good ideas on what state information would be useful for
>> a rate control to demand?
>
> Well, there are already hooks to fake the TX time spent, right? Having
> both TX and RX busy times available to rate control so it can better
> schedule TX loads based on current RX workloads would be nice.
>
> Having access to schedule which peer and how much to send to each peer
> would be nice. Stuff like "peer X only can have up to x ms in this WME
> class this round", so you don't have a busy, close peer monopolising
> the air. It also means you can start doing smart things with far away
> peers who retransmit a lot - they're likely tying up a lot of airtime.
>
> None of this is new. It's just, you know, new to open source. :-)
In my opinion this doesn't really belong into a rate control module.
There should be a tx scheduling API to take care of this. Before I
implement something like this, I plan on exposing all per-station driver
queues to mac80211. This is necessary for a few other things anyway,
e.g. unifying software aggregation logic and fixing its buffer management.

- Felix

2013-03-01 15:35:26

by Ben Greear

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 03/01/2013 06:31 AM, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> What was the distance and what was the rate used?
>
> A distance of about a meter between the AP and STA.
>
> AP: DB120 - running an internal build.
> STA: WB222 - wireless-testing HEAD.
> Signal is about -43 dBm.
> Channel 40, HT40-
>
> I've attached sample runs with minstrel_ht and ath9k-rc. With minstrel_ht,
> the numbers fluctuate between 180 and 190 Mbps and the average throughput
> varies each time (185, 186 etc.). With ath9k-rc, it's 195+ always.

We can run some tests through attenuators today.

I assume UDP would be good, or is TCP traffic preferred?
(In our tests, we see significantly more throughput with
UDP than TCP, even when we hacked on TCP ack delay).

Is wireless-testing the preferred tree to test against?

Thanks,
Ben

>
> Sujith
>


--
Ben Greear <[email protected]>
Candela Technologies Inc http://www.candelatech.com


2013-03-01 10:29:24

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-03-01 11:22 AM, Adrian Chadd wrote:
> On 1 March 2013 02:14, Felix Fietkau <[email protected]> wrote:
>
>>> Having access to schedule which peer and how much to send to each peer
>>> would be nice. Stuff like "peer X only can have up to x ms in this WME
>>> class this round", so you don't have a busy, close peer monopolising
>>> the air. It also means you can start doing smart things with far away
>>> peers who retransmit a lot - they're likely tying up a lot of airtime.
>>>
>>> None of this is new. It's just, you know, new to open source. :-)
>
>> In my opinion this doesn't really belong into a rate control module.
>> There should be a tx scheduling API to take care of this. Before I
>> implement something like this, I plan on exposing all per-station driver
>> queues to mac80211. This is necessary for a few other things anyway,
>> e.g. unifying software aggregation logic and fixing its buffer management.
>
> Sure, but then some more clever tricks end up being difficult to
> implement. For example, knowing if a client is tying up too much
> airtime at the given rate and whether to back them off for a bit. Or
> to use smaller aggregation limits for certain clients because your'e
> trying to be "fairer" when trying to keep latency low. That kind of
> thing.
>
> I think "rate control" should likely be expanded to "tx scheduling" as
> a whole, rather than sitting as a separate thing that just selects the
> rate for a node who has already been chosen to transmit.
Even with client airtime use, I still don't see how tx scheduling and
rate control belong together. In my opinion, the rate selection should
not be based on client airtime usage or the current load, as it can
optimize for throughput/airtime ratio without it.

- Felix

2013-03-01 21:28:12

by Adrian Chadd

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 1 March 2013 06:31, Sujith Manoharan <[email protected]> wrote:
> Felix Fietkau wrote:
>> What was the distance and what was the rate used?
>
> A distance of about a meter between the AP and STA.
>
> AP: DB120 - running an internal build.
> STA: WB222 - wireless-testing HEAD.
> Signal is about -43 dBm.
> Channel 40, HT40-
>
> I've attached sample runs with minstrel_ht and ath9k-rc. With minstrel_ht,
> the numbers fluctuate between 180 and 190 Mbps and the average throughput
> varies each time (185, 186 etc.). With ath9k-rc, it's 195+ always.

Right. And the reason that it fluctuates is quite likely because at
the higher MCS rates (6,7/14,15/22,23) the channel behaviour is not
consistent and there's varying levels of packet loss, so things
oscillate between a bunch of MCS rates there.

IIRC, the ath9k_rc algorithm is a lot more aggressive at sticking to a
fixed, working MCS rate.

(190mbit TCP on 2-stream? Damn. Looks like I have a little more
optimisation to do in FreeBSD. I'm only hitting 160/170mbit TCP on
AR9280<->AR9280 and AR9280<->AR9287. But I hit 220-240mbit UDP.)

Thanks,


Adrian

2013-03-02 20:23:44

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-03-01 3:31 PM, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> What was the distance and what was the rate used?
>
> A distance of about a meter between the AP and STA.
>
> AP: DB120 - running an internal build.
> STA: WB222 - wireless-testing HEAD.
> Signal is about -43 dBm.
> Channel 40, HT40-
>
> I've attached sample runs with minstrel_ht and ath9k-rc. With minstrel_ht,
> the numbers fluctuate between 180 and 190 Mbps and the average throughput
> varies each time (185, 186 etc.). With ath9k-rc, it's 195+ always.
I just sent some minstrel_ht improvements to linux-wireless@
Please test if they fix the throughput delta in your setup. In my tests
they visibly reduce the number of unnecessary fallbacks to lower rates.

Thanks,

- Felix

2013-03-03 04:00:16

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Felix Fietkau wrote:
> I just sent some minstrel_ht improvements to linux-wireless@
> Please test if they fix the throughput delta in your setup. In my tests
> they visibly reduce the number of unnecessary fallbacks to lower rates.

With the fixes, the avg. TX throughput crept up to 188 Mbps, but I ran
ath9k-rc once again and obtained 197 Mbps. There were lots of 200+ Mbps
max. throughput too.

This is not a synthetic benchmark with shield boxes, attenuators etc.,
just a simple over-the-air test with not much interference, so a gap of
~10 Mbps is somewhat surprising.

Sujith

2013-03-01 10:22:30

by Adrian Chadd

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 1 March 2013 02:14, Felix Fietkau <[email protected]> wrote:

>> Having access to schedule which peer and how much to send to each peer
>> would be nice. Stuff like "peer X only can have up to x ms in this WME
>> class this round", so you don't have a busy, close peer monopolising
>> the air. It also means you can start doing smart things with far away
>> peers who retransmit a lot - they're likely tying up a lot of airtime.
>>
>> None of this is new. It's just, you know, new to open source. :-)

> In my opinion this doesn't really belong into a rate control module.
> There should be a tx scheduling API to take care of this. Before I
> implement something like this, I plan on exposing all per-station driver
> queues to mac80211. This is necessary for a few other things anyway,
> e.g. unifying software aggregation logic and fixing its buffer management.

Sure, but then some more clever tricks end up being difficult to
implement. For example, knowing if a client is tying up too much
airtime at the given rate and whether to back them off for a bit. Or
to use smaller aggregation limits for certain clients because your'e
trying to be "fairer" when trying to keep latency low. That kind of
thing.

I think "rate control" should likely be expanded to "tx scheduling" as
a whole, rather than sitting as a separate thing that just selects the
rate for a node who has already been chosen to transmit.



Adrian

2013-03-01 03:53:56

by Adrian Chadd

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 28 February 2013 11:07, Felix Fietkau <[email protected]> wrote:

>> Personally, I'd like to see more examples of rate control modules in
>> LInux/FreeBSD, especially ones that start demanding more 802.11 state
>> (ie, air-time QoS.)

> Do you have any good ideas on what state information would be useful for
> a rate control to demand?

Well, there are already hooks to fake the TX time spent, right? Having
both TX and RX busy times available to rate control so it can better
schedule TX loads based on current RX workloads would be nice.

Having access to schedule which peer and how much to send to each peer
would be nice. Stuff like "peer X only can have up to x ms in this WME
class this round", so you don't have a busy, close peer monopolising
the air. It also means you can start doing smart things with far away
peers who retransmit a lot - they're likely tying up a lot of airtime.

None of this is new. It's just, you know, new to open source. :-)



Adrian

2013-03-01 01:24:40

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

Felix Fietkau wrote:
> In that case I'd rather keep PID than the ath9k rate control. The ath9k
> rate control is a horrible example of how to use the rate control API,
> and fixing that is a waste of time in my opinion.

I acked the earlier RFC patch to remove the ath9k RC as I assumed that minstrel_ht
would perform adequately, if not better. But, there appear to be areas in which
the numbers given by minstrel_ht are sub-optimal and which can be improved if we
have something to compare it with. The ath9k RC code is crap, no doubt, but I'd
prefer to have it for some time in the tree - we can switch the default RC to minstrel_ht
by default.

Can you also explain how the ath9k RC uses the mac80211 API horribly ? The algorithm might be
terribly implemented and the internal code nasty, but how does it violate the API ?

Sujith

2013-03-01 13:06:06

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-03-01 1:32 PM, Mohammed Shafi wrote:
> On Fri, Mar 1, 2013 at 5:01 PM, Felix Fietkau <[email protected]> wrote:
>> On 2013-03-01 12:18 PM, Mohammed Shafi wrote:
>>> Hi Felix,
>>>
>>> On Fri, Mar 1, 2013 at 3:59 PM, Felix Fietkau <[email protected]> wrote:
>>>> On 2013-03-01 11:22 AM, Adrian Chadd wrote:
>>>>> On 1 March 2013 02:14, Felix Fietkau <[email protected]> wrote:
>>>>>
>>>>>>> Having access to schedule which peer and how much to send to each peer
>>>>>>> would be nice. Stuff like "peer X only can have up to x ms in this WME
>>>>>>> class this round", so you don't have a busy, close peer monopolising
>>>>>>> the air. It also means you can start doing smart things with far away
>>>>>>> peers who retransmit a lot - they're likely tying up a lot of airtime.
>>>>>>>
>>>>>>> None of this is new. It's just, you know, new to open source. :-)
>>>>>
>>>>>> In my opinion this doesn't really belong into a rate control module.
>>>>>> There should be a tx scheduling API to take care of this. Before I
>>>>>> implement something like this, I plan on exposing all per-station driver
>>>>>> queues to mac80211. This is necessary for a few other things anyway,
>>>>>> e.g. unifying software aggregation logic and fixing its buffer management.
>>>>>
>>>>> Sure, but then some more clever tricks end up being difficult to
>>>>> implement. For example, knowing if a client is tying up too much
>>>>> airtime at the given rate and whether to back them off for a bit. Or
>>>>> to use smaller aggregation limits for certain clients because your'e
>>>>> trying to be "fairer" when trying to keep latency low. That kind of
>>>>> thing.
>>>>>
>>>>> I think "rate control" should likely be expanded to "tx scheduling" as
>>>>> a whole, rather than sitting as a separate thing that just selects the
>>>>> rate for a node who has already been chosen to transmit.
>>>> Even with client airtime use, I still don't see how tx scheduling and
>>>> rate control belong together. In my opinion, the rate selection should
>>>> not be based on client airtime usage or the current load, as it can
>>>> optimize for throughput/airtime ratio without it.
>>>>
>>>
>>> Algorithm folks and Engineers had spent considerable time on ath9k rate control.
>>> Wouldn't be a great idea to remove it completely, We can have it optional.
>>> With lot of throughput tests ran over internally and with the test
>>> team verification,
>>> it wouldn't be fair to throw it away.
>> Regardless of how much time was spent tuning it, it still has a really
>> bad design, bad implementation and a number of practical issues.
>> It seems to be tuned entirely for artificial benchmarks in clean air. It
>> also starts with a very high rate without having proven that it works.
>> I don't think anybody is going to fix all of these issues, and even if
>> somebody does, it would invalidate pretty much all of the tuning/testing
>> that went into this code.
>>
>
> We can certainly question the design and implementation, but it was proven
> to work well and had been tested by more hands(even with propitiatory stuff).
> Even if some one thinks it as bad, we should still allow it as an option.
> For instance if the environment is pretty good/pretty bad, we should give
> the users an option to choose between the two, that's why we should retain
> it.
I agree that we should keep it for a while, but we should probably
change the default soon. As for giving *users* the option of choosing
rate control based on the environment, I think it's a bad idea! Regular
users can't really be expected to know enough about the details of rate
control to make a meaningful decision, nor should they be. Simply being
lazy and telling every user to just test which one works better for them
is also a bad idea.

The default implementation needs to be good for all kinds of
environments. minstrel_ht is already tuned to work quite well in tough
environments with heavy interference, so closing the performance gap in
clean environments should be quite easy. The main thing I need to get
that done is good quality test feedback - something that I didn't get a
lot of, neither from users, nor from QCA.

> Further its been tested internally, by customers and more folks.
Right, and a few of those customers complained about bad performance
with ath9k, and also reported that switching to minstrel_ht fixed their
issues :)
Good to know that it's been tested, but where are the results? Who is
going to take care of the long standing *known* issues?
One of these issues (too high bitrate before rate feedback is available)
led to somebody from Google hacking up a crappy workaround in
wpa_supplicant that disables high bitrates during connect.

Saying that it has been tested does not necessarily imply that it's any
good or that it works properly in all normal scenarios ;)

> Its been also worked by some serious developers and Engineers.
Well, I do consider myself a serious developer and engineer as well :)

- Felix

2013-03-02 08:26:37

by Georgiewskiy Yuriy

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-03-01 21:40 -0800, Adrian Chadd wrote Sujith Manoharan:

AC>On 1 March 2013 18:19, Sujith Manoharan <[email protected]> wrote:
AC>> Adrian Chadd wrote:
AC>>> (190mbit TCP on 2-stream? Damn. Looks like I have a little more
AC>>> optimisation to do in FreeBSD. I'm only hitting 160/170mbit TCP on
AC>>> AR9280<->AR9280 and AR9280<->AR9287. But I hit 220-240mbit UDP.)
AC>>
AC>> I used a AR9462 card for this test. With AR9280/AR9287 I get abysmal
AC>> numbers with both rate control algorithms. Maybe something has regressed
AC>> in ath9k for the AR9002 family...
AC>
AC>It's almost like we need some kind of lab space set aside for running
AC>regression tests with all of the ath9k hardware ,dating back to
AC>AR5416, with some automated testing rigs..

Think this is good idea, have same problem - no mo ~50 megabit on ar9002.

AC>I have the hardware. Who wants to do it? :)


C ????????? With Best Regards
???????????? ????. Georgiewskiy Yuriy
+7 4872 711666 +7 4872 711666
???? +7 4872 711143 fax +7 4872 711143
???????? ??? "?? ?? ??????" IT Service Ltd
http://nkoort.ru http://nkoort.ru
JID: [email protected] JID: [email protected]
YG129-RIPE YG129-RIPE

2013-03-01 12:33:00

by Mohammed Shafi

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On Fri, Mar 1, 2013 at 5:01 PM, Felix Fietkau <[email protected]> wrote:
> On 2013-03-01 12:18 PM, Mohammed Shafi wrote:
>> Hi Felix,
>>
>> On Fri, Mar 1, 2013 at 3:59 PM, Felix Fietkau <[email protected]> wrote:
>>> On 2013-03-01 11:22 AM, Adrian Chadd wrote:
>>>> On 1 March 2013 02:14, Felix Fietkau <[email protected]> wrote:
>>>>
>>>>>> Having access to schedule which peer and how much to send to each peer
>>>>>> would be nice. Stuff like "peer X only can have up to x ms in this WME
>>>>>> class this round", so you don't have a busy, close peer monopolising
>>>>>> the air. It also means you can start doing smart things with far away
>>>>>> peers who retransmit a lot - they're likely tying up a lot of airtime.
>>>>>>
>>>>>> None of this is new. It's just, you know, new to open source. :-)
>>>>
>>>>> In my opinion this doesn't really belong into a rate control module.
>>>>> There should be a tx scheduling API to take care of this. Before I
>>>>> implement something like this, I plan on exposing all per-station driver
>>>>> queues to mac80211. This is necessary for a few other things anyway,
>>>>> e.g. unifying software aggregation logic and fixing its buffer management.
>>>>
>>>> Sure, but then some more clever tricks end up being difficult to
>>>> implement. For example, knowing if a client is tying up too much
>>>> airtime at the given rate and whether to back them off for a bit. Or
>>>> to use smaller aggregation limits for certain clients because your'e
>>>> trying to be "fairer" when trying to keep latency low. That kind of
>>>> thing.
>>>>
>>>> I think "rate control" should likely be expanded to "tx scheduling" as
>>>> a whole, rather than sitting as a separate thing that just selects the
>>>> rate for a node who has already been chosen to transmit.
>>> Even with client airtime use, I still don't see how tx scheduling and
>>> rate control belong together. In my opinion, the rate selection should
>>> not be based on client airtime usage or the current load, as it can
>>> optimize for throughput/airtime ratio without it.
>>>
>>
>> Algorithm folks and Engineers had spent considerable time on ath9k rate control.
>> Wouldn't be a great idea to remove it completely, We can have it optional.
>> With lot of throughput tests ran over internally and with the test
>> team verification,
>> it wouldn't be fair to throw it away.
> Regardless of how much time was spent tuning it, it still has a really
> bad design, bad implementation and a number of practical issues.
> It seems to be tuned entirely for artificial benchmarks in clean air. It
> also starts with a very high rate without having proven that it works.
> I don't think anybody is going to fix all of these issues, and even if
> somebody does, it would invalidate pretty much all of the tuning/testing
> that went into this code.
>

We can certainly question the design and implementation, but it was proven
to work well and had been tested by more hands(even with propitiatory stuff).
Even if some one thinks it as bad, we should still allow it as an option.
For instance if the environment is pretty good/pretty bad, we should give
the users an option to choose between the two, that's why we should retain
it. Further its been tested internally, by customers and more folks. Its been
also worked by some serious developers and Engineers.


--
thanks,
shafi

2013-03-01 14:33:30

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

root@linux-test ~# iperf -i1 -c 172.16.1.222 -t 120 -P 4
------------------------------------------------------------
Client connecting to 172.16.1.222, TCP port 5001
TCP window size: 22.9 KByte (default)
------------------------------------------------------------
[ 5] local 172.16.1.111 port 36820 connected with 172.16.1.222 port 5001
[ 4] local 172.16.1.111 port 36819 connected with 172.16.1.222 port 5001
[ 3] local 172.16.1.111 port 36821 connected with 172.16.1.222 port 5001
[ 6] local 172.16.1.111 port 36822 connected with 172.16.1.222 port 5001

685:[SUM] 0.0- 1.0 sec 21.0 MBytes 176 Mbits/sec
690:[SUM] 1.0- 2.0 sec 21.8 MBytes 182 Mbits/sec
695:[SUM] 2.0- 3.0 sec 21.8 MBytes 182 Mbits/sec
700:[SUM] 3.0- 4.0 sec 22.8 MBytes 191 Mbits/sec
705:[SUM] 4.0- 5.0 sec 22.5 MBytes 189 Mbits/sec
710:[SUM] 5.0- 6.0 sec 22.9 MBytes 192 Mbits/sec
715:[SUM] 6.0- 7.0 sec 22.2 MBytes 187 Mbits/sec
720:[SUM] 7.0- 8.0 sec 22.0 MBytes 185 Mbits/sec
725:[SUM] 8.0- 9.0 sec 23.1 MBytes 194 Mbits/sec
730:[SUM] 9.0-10.0 sec 21.9 MBytes 184 Mbits/sec
735:[SUM] 10.0-11.0 sec 22.5 MBytes 189 Mbits/sec
740:[SUM] 11.0-12.0 sec 22.1 MBytes 186 Mbits/sec
745:[SUM] 12.0-13.0 sec 22.5 MBytes 189 Mbits/sec
750:[SUM] 13.0-14.0 sec 23.0 MBytes 193 Mbits/sec
755:[SUM] 14.0-15.0 sec 21.5 MBytes 180 Mbits/sec
760:[SUM] 15.0-16.0 sec 22.5 MBytes 189 Mbits/sec
765:[SUM] 16.0-17.0 sec 22.8 MBytes 191 Mbits/sec
770:[SUM] 17.0-18.0 sec 22.8 MBytes 191 Mbits/sec
775:[SUM] 18.0-19.0 sec 21.9 MBytes 184 Mbits/sec
780:[SUM] 19.0-20.0 sec 21.1 MBytes 177 Mbits/sec
785:[SUM] 20.0-21.0 sec 22.8 MBytes 191 Mbits/sec
790:[SUM] 21.0-22.0 sec 22.5 MBytes 189 Mbits/sec
795:[SUM] 22.0-23.0 sec 22.5 MBytes 189 Mbits/sec
800:[SUM] 23.0-24.0 sec 22.6 MBytes 190 Mbits/sec
805:[SUM] 24.0-25.0 sec 21.5 MBytes 180 Mbits/sec
810:[SUM] 25.0-26.0 sec 22.1 MBytes 186 Mbits/sec
815:[SUM] 26.0-27.0 sec 22.1 MBytes 186 Mbits/sec
820:[SUM] 27.0-28.0 sec 21.6 MBytes 181 Mbits/sec
825:[SUM] 28.0-29.0 sec 22.6 MBytes 190 Mbits/sec
830:[SUM] 29.0-30.0 sec 23.0 MBytes 193 Mbits/sec
835:[SUM] 30.0-31.0 sec 22.8 MBytes 191 Mbits/sec
840:[SUM] 31.0-32.0 sec 22.6 MBytes 190 Mbits/sec
845:[SUM] 32.0-33.0 sec 21.9 MBytes 184 Mbits/sec
850:[SUM] 33.0-34.0 sec 21.6 MBytes 181 Mbits/sec
855:[SUM] 34.0-35.0 sec 22.9 MBytes 192 Mbits/sec
860:[SUM] 35.0-36.0 sec 22.0 MBytes 185 Mbits/sec
865:[SUM] 36.0-37.0 sec 22.6 MBytes 190 Mbits/sec
870:[SUM] 37.0-38.0 sec 22.2 MBytes 187 Mbits/sec
875:[SUM] 38.0-39.0 sec 22.5 MBytes 189 Mbits/sec
880:[SUM] 39.0-40.0 sec 21.9 MBytes 184 Mbits/sec
885:[SUM] 40.0-41.0 sec 22.6 MBytes 190 Mbits/sec
890:[SUM] 41.0-42.0 sec 22.2 MBytes 187 Mbits/sec
895:[SUM] 42.0-43.0 sec 21.9 MBytes 184 Mbits/sec
900:[SUM] 43.0-44.0 sec 22.4 MBytes 188 Mbits/sec
905:[SUM] 44.0-45.0 sec 20.5 MBytes 172 Mbits/sec
910:[SUM] 45.0-46.0 sec 22.4 MBytes 188 Mbits/sec
915:[SUM] 46.0-47.0 sec 23.0 MBytes 193 Mbits/sec
920:[SUM] 47.0-48.0 sec 21.8 MBytes 182 Mbits/sec
925:[SUM] 48.0-49.0 sec 22.2 MBytes 187 Mbits/sec
930:[SUM] 49.0-50.0 sec 22.4 MBytes 188 Mbits/sec
935:[SUM] 50.0-51.0 sec 22.4 MBytes 188 Mbits/sec
940:[SUM] 51.0-52.0 sec 23.1 MBytes 194 Mbits/sec
945:[SUM] 52.0-53.0 sec 22.4 MBytes 188 Mbits/sec
950:[SUM] 53.0-54.0 sec 22.6 MBytes 190 Mbits/sec
955:[SUM] 54.0-55.0 sec 22.8 MBytes 191 Mbits/sec
960:[SUM] 55.0-56.0 sec 22.4 MBytes 188 Mbits/sec
965:[SUM] 56.0-57.0 sec 22.5 MBytes 189 Mbits/sec
970:[SUM] 57.0-58.0 sec 23.0 MBytes 193 Mbits/sec
975:[SUM] 58.0-59.0 sec 22.1 MBytes 186 Mbits/sec
980:[SUM] 59.0-60.0 sec 21.8 MBytes 182 Mbits/sec
985:[SUM] 60.0-61.0 sec 21.6 MBytes 181 Mbits/sec
990:[SUM] 61.0-62.0 sec 22.6 MBytes 190 Mbits/sec
995:[SUM] 62.0-63.0 sec 22.1 MBytes 186 Mbits/sec
1000:[SUM] 63.0-64.0 sec 21.8 MBytes 182 Mbits/sec
1005:[SUM] 64.0-65.0 sec 22.2 MBytes 187 Mbits/sec
1010:[SUM] 65.0-66.0 sec 21.8 MBytes 182 Mbits/sec
1015:[SUM] 66.0-67.0 sec 22.2 MBytes 187 Mbits/sec
1020:[SUM] 67.0-68.0 sec 22.2 MBytes 187 Mbits/sec
1025:[SUM] 68.0-69.0 sec 23.2 MBytes 195 Mbits/sec
1030:[SUM] 69.0-70.0 sec 23.2 MBytes 195 Mbits/sec
1035:[SUM] 70.0-71.0 sec 22.5 MBytes 189 Mbits/sec
1040:[SUM] 71.0-72.0 sec 22.2 MBytes 187 Mbits/sec
1045:[SUM] 72.0-73.0 sec 22.0 MBytes 185 Mbits/sec
1050:[SUM] 73.0-74.0 sec 21.9 MBytes 184 Mbits/sec
1055:[SUM] 74.0-75.0 sec 22.5 MBytes 189 Mbits/sec
1060:[SUM] 75.0-76.0 sec 22.4 MBytes 188 Mbits/sec
1065:[SUM] 76.0-77.0 sec 22.6 MBytes 190 Mbits/sec
1070:[SUM] 77.0-78.0 sec 22.9 MBytes 192 Mbits/sec
1075:[SUM] 78.0-79.0 sec 22.1 MBytes 186 Mbits/sec
1080:[SUM] 79.0-80.0 sec 22.0 MBytes 185 Mbits/sec
1085:[SUM] 80.0-81.0 sec 21.9 MBytes 184 Mbits/sec
1090:[SUM] 81.0-82.0 sec 21.5 MBytes 180 Mbits/sec
1095:[SUM] 82.0-83.0 sec 22.4 MBytes 188 Mbits/sec
1100:[SUM] 83.0-84.0 sec 23.4 MBytes 196 Mbits/sec
1105:[SUM] 84.0-85.0 sec 22.0 MBytes 185 Mbits/sec
1110:[SUM] 85.0-86.0 sec 22.5 MBytes 189 Mbits/sec
1115:[SUM] 86.0-87.0 sec 22.8 MBytes 191 Mbits/sec
1120:[SUM] 87.0-88.0 sec 22.4 MBytes 188 Mbits/sec
1125:[SUM] 88.0-89.0 sec 22.1 MBytes 186 Mbits/sec
1130:[SUM] 89.0-90.0 sec 22.8 MBytes 191 Mbits/sec
1135:[SUM] 90.0-91.0 sec 21.4 MBytes 179 Mbits/sec
1140:[SUM] 91.0-92.0 sec 22.4 MBytes 188 Mbits/sec
1145:[SUM] 92.0-93.0 sec 22.9 MBytes 192 Mbits/sec
1150:[SUM] 93.0-94.0 sec 22.9 MBytes 192 Mbits/sec
1155:[SUM] 94.0-95.0 sec 23.4 MBytes 196 Mbits/sec
1160:[SUM] 95.0-96.0 sec 21.1 MBytes 177 Mbits/sec
1165:[SUM] 96.0-97.0 sec 22.0 MBytes 185 Mbits/sec
1170:[SUM] 97.0-98.0 sec 22.2 MBytes 187 Mbits/sec
1175:[SUM] 98.0-99.0 sec 22.5 MBytes 189 Mbits/sec
1180:[SUM] 99.0-100.0 sec 22.2 MBytes 187 Mbits/sec
1185:[SUM] 100.0-101.0 sec 22.4 MBytes 188 Mbits/sec
1190:[SUM] 101.0-102.0 sec 22.5 MBytes 189 Mbits/sec
1195:[SUM] 102.0-103.0 sec 23.0 MBytes 193 Mbits/sec
1200:[SUM] 103.0-104.0 sec 22.0 MBytes 185 Mbits/sec
1205:[SUM] 104.0-105.0 sec 22.0 MBytes 185 Mbits/sec
1210:[SUM] 105.0-106.0 sec 22.5 MBytes 189 Mbits/sec
1215:[SUM] 106.0-107.0 sec 22.1 MBytes 186 Mbits/sec
1220:[SUM] 107.0-108.0 sec 22.4 MBytes 188 Mbits/sec
1225:[SUM] 108.0-109.0 sec 22.8 MBytes 191 Mbits/sec
1230:[SUM] 109.0-110.0 sec 22.4 MBytes 188 Mbits/sec
1235:[SUM] 110.0-111.0 sec 22.2 MBytes 187 Mbits/sec
1240:[SUM] 111.0-112.0 sec 22.9 MBytes 192 Mbits/sec
1245:[SUM] 112.0-113.0 sec 23.1 MBytes 194 Mbits/sec
1250:[SUM] 113.0-114.0 sec 23.1 MBytes 194 Mbits/sec
1255:[SUM] 114.0-115.0 sec 21.8 MBytes 182 Mbits/sec
1260:[SUM] 115.0-116.0 sec 21.5 MBytes 180 Mbits/sec
1265:[SUM] 116.0-117.0 sec 22.0 MBytes 185 Mbits/sec
1270:[SUM] 117.0-118.0 sec 21.8 MBytes 182 Mbits/sec
1275:[SUM] 118.0-119.0 sec 23.1 MBytes 194 Mbits/sec
1283:[SUM] 119.0-120.0 sec 23.2 MBytes 195 Mbits/sec

1285:[SUM] 0.0-120.0 sec 2.62 GBytes 187 Mbits/sec


cat /sys/kernel/debug/ieee80211/phy3/netdev:wlan0/stations/00:03:7f:42:08:56/rc_stats

type rate throughput ewma prob this prob retry this succ/attempt success attempts
HT20/LGI MCS0 6.6 99.9 100.0 2 0( 0) 86 91
HT20/LGI MCS1 10.5 81.1 100.0 2 0( 0) 90 96
HT20/LGI MCS2 17.5 91.8 100.0 2 0( 0) 88 91
HT20/LGI MCS3 24.9 99.6 100.0 2 0( 0) 85 92
HT20/LGI MCS4 36.0 99.2 100.0 2 0( 0) 88 92
HT20/LGI MCS5 42.8 92.0 100.0 2 0( 0) 85 90
HT20/LGI MCS6 48.2 94.0 100.0 2 0( 0) 85 95
HT20/LGI MCS7 57.1 99.9 100.0 2 0( 0) 92 95
HT20/LGI MCS8 12.9 99.5 100.0 2 0( 0) 89 93
HT20/LGI MCS9 24.1 96.4 100.0 2 0( 0) 91 96
HT20/LGI MCS10 36.3 99.9 100.0 2 0( 0) 86 91
HT20/LGI MCS11 46.5 99.9 100.0 2 0( 0) 92 96
HT20/LGI MCS12 60.3 91.1 100.0 2 0( 0) 89 93
HT20/LGI MCS13 81.1 99.8 100.0 2 0( 0) 86 93
HT20/LGI MCS14 90.0 99.9 100.0 2 0( 0) 91 96
HT20/LGI MCS15 83.4 85.9 100.0 2 0( 0) 97 99
HT20/SGI MCS0 7.3 99.6 100.0 2 0( 0) 87 93
HT20/SGI MCS1 14.4 99.9 100.0 2 0( 0) 88 93
HT20/SGI MCS2 20.9 99.3 100.0 2 0( 0) 88 93
HT20/SGI MCS3 27.4 99.3 100.0 2 0( 0) 90 96
HT20/SGI MCS4 37.9 95.2 100.0 2 0( 0) 83 92
HT20/SGI MCS5 48.4 95.5 100.0 2 0( 0) 87 93
HT20/SGI MCS6 55.6 99.6 100.0 2 0( 0) 93 100
HT20/SGI MCS7 60.9 98.1 100.0 2 0( 0) 93 95
HT20/SGI MCS8 13.7 95.3 100.0 2 0( 0) 82 90
HT20/SGI MCS9 26.8 97.3 100.0 2 0( 0) 84 90
HT20/SGI MCS10 39.8 99.9 100.0 2 0( 0) 90 91
HT20/SGI MCS11 50.7 99.9 100.0 2 0( 0) 87 92
HT20/SGI MCS12 71.1 98.9 100.0 2 0( 0) 85 89
HT20/SGI MCS13 80.2 91.4 100.0 2 0( 0) 87 91
HT20/SGI MCS14 97.0 99.9 100.0 2 0( 0) 92 97
HT20/SGI MCS15 78.0 74.9 0.0 2 0( 0) 476 538
HT40/LGI MCS0 13.5 99.8 100.0 2 0( 0) 90 95
HT40/LGI MCS1 26.0 99.9 100.0 2 0( 0) 86 90
HT40/LGI MCS2 36.1 96.6 100.0 2 0( 0) 89 92
HT40/LGI MCS3 44.4 92.0 100.0 2 0( 0) 91 94
HT40/LGI MCS4 61.7 90.7 100.0 2 0( 0) 86 93
HT40/LGI MCS5 70.1 83.4 100.0 2 0( 0) 81 91
HT40/LGI MCS6 85.9 92.0 100.0 2 0( 0) 91 96
HT40/LGI MCS7 100.6 99.6 100.0 2 0( 0) 88 94
HT40/LGI MCS8 25.5 97.9 100.0 2 0( 0) 83 92
HT40/LGI MCS9 44.4 92.0 100.0 2 0( 0) 84 90
HT40/LGI MCS10 67.7 99.5 100.0 2 0( 0) 81 91
HT40/LGI MCS11 59.2 70.5 0.0 2 0( 0) 85 89
HT40/LGI MCS12 105.8 92.0 100.0 3 0( 0) 90 93
HT40/LGI MCS13 118.3 88.7 100.0 3 0( 0) 84 89
HT40/LGI MCS14 145.4 97.4 100.0 4 0( 0) 768 899
HT40/LGI MCS15 130.0 81.9 100.0 4 0( 0) 80856 88875
HT40/SGI MCS0 14.9 99.9 100.0 2 0( 0) 86 91
HT40/SGI MCS1 21.4 74.7 0.0 2 0( 0) 91 95
HT40/SGI MCS2 41.1 99.9 100.0 2 0( 0) 85 91
HT40/SGI MCS3 49.7 93.9 100.0 2 0( 0) 88 93
HT40/SGI MCS4 55.4 74.8 0.0 2 0( 0) 88 92
HT40/SGI MCS5 86.9 95.6 100.0 2 0( 0) 85 91
HT40/SGI MCS6 100.9 99.9 100.0 2 0( 0) 86 94
HT40/SGI P MCS7 106.9 98.4 100.0 5 0( 0) 4424 4980
HT40/SGI MCS8 28.6 99.8 100.0 2 0( 0) 87 89
HT40/SGI MCS9 45.1 85.3 100.0 2 0( 0) 85 91
HT40/SGI MCS10 72.6 98.1 100.0 2 0( 0) 88 90
HT40/SGI MCS11 89.9 98.9 100.0 2 0( 0) 80 88
HT40/SGI MCS12 121.9 98.7 100.0 3 0( 0) 86 92
HT40/SGI MCS13 132.4 94.0 100.0 3 0( 0) 85 89
HT40/SGI t MCS14 152.6 96.1 100.0 5 0( 0) 88243 96781
HT40/SGI T MCS15 161.8 97.1 100.0 5 1( 1) 1760690 1945362

Total packet count:: ideal 1934621 lookaround 5901
Average A-MPDU length: 4.4


cat /sys/kernel/debug/ieee80211/phy3/ath9k/xmit

BE BK VI VO

MPDUs Queued: 10 0 0 47
MPDUs Completed: 10 0 0 47
MPDUs XRetried: 0 0 0 0
Aggregates: 63956 0 0 0
AMPDUs Queued HW: 99 0 0 0
AMPDUs Queued SW: 1940401 0 0 0
AMPDUs Completed: 1940500 0 0 0
AMPDUs Retried: 14536 0 0 0
AMPDUs XRetried: 0 0 0 0
FIFO Underrun: 0 0 0 0
TXOP Exceeded: 0 0 0 0
TXTIMER Expiry: 0 0 0 0
DESC CFG Error: 0 0 0 0
DATA Underrun: 0 0 0 0
DELIM Underrun: 0 0 0 0
TX-Pkts-All: 1940510 0 0 47
TX-Bytes-All: 2980293154 0 0 2296
HW-put-tx-buf: 70308 0 0 47
HW-tx-start: 0 0 0 0
HW-tx-proc-desc: 70308 0 0 47
TX-Failed: 0 0 0 0


Attachments:
ath9k-rc.txt (9.82 kB)
ath9k-rc
minstrel_ht.txt (15.74 kB)
minstrel_ht
Download all attachments

2013-03-01 21:23:28

by Adrian Chadd

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 1 March 2013 07:35, Ben Greear <[email protected]> wrote:

> I assume UDP would be good, or is TCP traffic preferred?
> (In our tests, we see significantly more throughput with
> UDP than TCP, even when we hacked on TCP ack delay).
>
> Is wireless-testing the preferred tree to test against?

Do both. Failures at higher MCS rates -> extra latency -> TCP backoff
-> crappier throughput.



Adrian

2013-03-01 11:31:12

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC] ath9k: remove ath9k_rate_control

On 2013-03-01 12:18 PM, Mohammed Shafi wrote:
> Hi Felix,
>
> On Fri, Mar 1, 2013 at 3:59 PM, Felix Fietkau <[email protected]> wrote:
>> On 2013-03-01 11:22 AM, Adrian Chadd wrote:
>>> On 1 March 2013 02:14, Felix Fietkau <[email protected]> wrote:
>>>
>>>>> Having access to schedule which peer and how much to send to each peer
>>>>> would be nice. Stuff like "peer X only can have up to x ms in this WME
>>>>> class this round", so you don't have a busy, close peer monopolising
>>>>> the air. It also means you can start doing smart things with far away
>>>>> peers who retransmit a lot - they're likely tying up a lot of airtime.
>>>>>
>>>>> None of this is new. It's just, you know, new to open source. :-)
>>>
>>>> In my opinion this doesn't really belong into a rate control module.
>>>> There should be a tx scheduling API to take care of this. Before I
>>>> implement something like this, I plan on exposing all per-station driver
>>>> queues to mac80211. This is necessary for a few other things anyway,
>>>> e.g. unifying software aggregation logic and fixing its buffer management.
>>>
>>> Sure, but then some more clever tricks end up being difficult to
>>> implement. For example, knowing if a client is tying up too much
>>> airtime at the given rate and whether to back them off for a bit. Or
>>> to use smaller aggregation limits for certain clients because your'e
>>> trying to be "fairer" when trying to keep latency low. That kind of
>>> thing.
>>>
>>> I think "rate control" should likely be expanded to "tx scheduling" as
>>> a whole, rather than sitting as a separate thing that just selects the
>>> rate for a node who has already been chosen to transmit.
>> Even with client airtime use, I still don't see how tx scheduling and
>> rate control belong together. In my opinion, the rate selection should
>> not be based on client airtime usage or the current load, as it can
>> optimize for throughput/airtime ratio without it.
>>
>
> Algorithm folks and Engineers had spent considerable time on ath9k rate control.
> Wouldn't be a great idea to remove it completely, We can have it optional.
> With lot of throughput tests ran over internally and with the test
> team verification,
> it wouldn't be fair to throw it away.
Regardless of how much time was spent tuning it, it still has a really
bad design, bad implementation and a number of practical issues.
It seems to be tuned entirely for artificial benchmarks in clean air. It
also starts with a very high rate without having proven that it works.
I don't think anybody is going to fix all of these issues, and even if
somebody does, it would invalidate pretty much all of the tuning/testing
that went into this code.

- Felix