ath9k: Use helpers
Break down huge functions, use helper functions or macros instead. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
@@ -153,11 +153,6 @@ static struct ath_rate_table ar5416_11na_ratetable = {
|
|||||||
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
|
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* VALID_ALL - valid for 20/40/Legacy,
|
|
||||||
* VALID - Legacy only,
|
|
||||||
* VALID_20 - HT 20 only,
|
|
||||||
* VALID_40 - HT 40 only */
|
|
||||||
|
|
||||||
/* 4ms frame limit not used for NG mode. The values filled
|
/* 4ms frame limit not used for NG mode. The values filled
|
||||||
* for HT are the 64K max aggregate limit */
|
* for HT are the 64K max aggregate limit */
|
||||||
|
|
||||||
@@ -471,8 +466,7 @@ static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv,
|
|||||||
return ath_rc_priv->valid_rate_index[index];
|
return ath_rc_priv->valid_rate_index[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
|
||||||
ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
|
|
||||||
struct ath_rate_priv *ath_rc_priv,
|
struct ath_rate_priv *ath_rc_priv,
|
||||||
u8 cur_valid_txrate,
|
u8 cur_valid_txrate,
|
||||||
u8 *next_idx)
|
u8 *next_idx)
|
||||||
@@ -488,6 +482,7 @@ ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
|
|||||||
|
|
||||||
/* No more valid rates */
|
/* No more valid rates */
|
||||||
*next_idx = 0;
|
*next_idx = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,11 +517,11 @@ ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8
|
static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
|
||||||
ath_rc_sib_init_validrates(struct ath_rate_priv *ath_rc_priv,
|
|
||||||
struct ath_rate_table *rate_table,
|
struct ath_rate_table *rate_table,
|
||||||
u32 capflag)
|
u32 capflag)
|
||||||
{
|
{
|
||||||
@@ -552,11 +547,11 @@ ath_rc_sib_init_validrates(struct ath_rate_priv *ath_rc_priv,
|
|||||||
hi = A_MAX(hi, i);
|
hi = A_MAX(hi, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hi;
|
return hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8
|
static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
|
||||||
ath_rc_sib_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
|
|
||||||
struct ath_rate_table *rate_table,
|
struct ath_rate_table *rate_table,
|
||||||
struct ath_rateset *rateset,
|
struct ath_rateset *rateset,
|
||||||
u32 capflag)
|
u32 capflag)
|
||||||
@@ -570,17 +565,17 @@ ath_rc_sib_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
|
|||||||
u32 valid = (ath_rc_priv->single_stream ?
|
u32 valid = (ath_rc_priv->single_stream ?
|
||||||
rate_table->info[j].valid_single_stream :
|
rate_table->info[j].valid_single_stream :
|
||||||
rate_table->info[j].valid);
|
rate_table->info[j].valid);
|
||||||
|
u8 rate = rateset->rs_rates[i];
|
||||||
|
u8 dot11rate = rate_table->info[j].dot11rate;
|
||||||
|
|
||||||
/* We allow a rate only if its valid and the
|
/* We allow a rate only if its valid and the
|
||||||
* capflag matches one of the validity
|
* capflag matches one of the validity
|
||||||
* (VALID/VALID_20/VALID_40) flags */
|
* (VALID/VALID_20/VALID_40) flags */
|
||||||
|
|
||||||
if (((rateset->rs_rates[i] & 0x7F) ==
|
if (((rate & 0x7F) == (dot11rate & 0x7F)) &&
|
||||||
(rate_table->info[j].dot11rate & 0x7F)) &&
|
|
||||||
((valid & WLAN_RC_CAP_MODE(capflag)) ==
|
((valid & WLAN_RC_CAP_MODE(capflag)) ==
|
||||||
WLAN_RC_CAP_MODE(capflag)) &&
|
WLAN_RC_CAP_MODE(capflag)) &&
|
||||||
!WLAN_RC_PHY_HT(phy)) {
|
!WLAN_RC_PHY_HT(phy)) {
|
||||||
|
|
||||||
u8 valid_rate_count = 0;
|
u8 valid_rate_count = 0;
|
||||||
|
|
||||||
if (!ath_rc_valid_phyrate(phy, capflag, 0))
|
if (!ath_rc_valid_phyrate(phy, capflag, 0))
|
||||||
@@ -597,27 +592,29 @@ ath_rc_sib_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hi;
|
return hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8
|
static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
|
||||||
ath_rc_sib_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
|
|
||||||
struct ath_rate_table *rate_table,
|
struct ath_rate_table *rate_table,
|
||||||
u8 *mcs_set, u32 capflag)
|
u8 *mcs_set, u32 capflag)
|
||||||
{
|
{
|
||||||
|
struct ath_rateset *rateset = (struct ath_rateset *)mcs_set;
|
||||||
|
|
||||||
u8 i, j, hi = 0;
|
u8 i, j, hi = 0;
|
||||||
|
|
||||||
/* Use intersection of working rates and valid rates */
|
/* Use intersection of working rates and valid rates */
|
||||||
for (i = 0; i < ((struct ath_rateset *)mcs_set)->rs_nrates; i++) {
|
for (i = 0; i < rateset->rs_nrates; i++) {
|
||||||
for (j = 0; j < rate_table->rate_cnt; j++) {
|
for (j = 0; j < rate_table->rate_cnt; j++) {
|
||||||
u32 phy = rate_table->info[j].phy;
|
u32 phy = rate_table->info[j].phy;
|
||||||
u32 valid = (ath_rc_priv->single_stream ?
|
u32 valid = (ath_rc_priv->single_stream ?
|
||||||
rate_table->info[j].valid_single_stream :
|
rate_table->info[j].valid_single_stream :
|
||||||
rate_table->info[j].valid);
|
rate_table->info[j].valid);
|
||||||
|
u8 rate = rateset->rs_rates[i];
|
||||||
|
u8 dot11rate = rate_table->info[j].dot11rate;
|
||||||
|
|
||||||
if (((((struct ath_rateset *)
|
if (((rate & 0x7F) != (dot11rate & 0x7F)) ||
|
||||||
mcs_set)->rs_rates[i] & 0x7F) !=
|
|
||||||
(rate_table->info[j].dot11rate & 0x7F)) ||
|
|
||||||
!WLAN_RC_PHY_HT(phy) ||
|
!WLAN_RC_PHY_HT(phy) ||
|
||||||
!WLAN_RC_PHY_HT_VALID(valid, capflag))
|
!WLAN_RC_PHY_HT_VALID(valid, capflag))
|
||||||
continue;
|
continue;
|
||||||
@@ -632,28 +629,10 @@ ath_rc_sib_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
|
|||||||
hi = A_MAX(hi, j);
|
hi = A_MAX(hi, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hi;
|
return hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 ath_rate_findrateix(struct ath_softc *sc,
|
|
||||||
u8 dot11rate)
|
|
||||||
{
|
|
||||||
struct ath_rate_table *ratetable;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ratetable = sc->hw_rate_table[sc->sc_curmode];
|
|
||||||
|
|
||||||
if (WARN_ON(!ratetable))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 0; i < ratetable->rate_cnt; i++) {
|
|
||||||
if ((ratetable->info[i].dot11rate & 0x7f) == (dot11rate & 0x7f))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
|
static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
|
||||||
struct ath_rate_priv *ath_rc_priv,
|
struct ath_rate_priv *ath_rc_priv,
|
||||||
struct ath_rate_table *rate_table,
|
struct ath_rate_table *rate_table,
|
||||||
@@ -784,9 +763,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
|
|||||||
|
|
||||||
static void ath_rc_rate_set_series(struct ath_rate_table *rate_table ,
|
static void ath_rc_rate_set_series(struct ath_rate_table *rate_table ,
|
||||||
struct ieee80211_tx_rate *rate,
|
struct ieee80211_tx_rate *rate,
|
||||||
u8 tries,
|
u8 tries, u8 rix, int rtsctsenable)
|
||||||
u8 rix,
|
|
||||||
int rtsctsenable)
|
|
||||||
{
|
{
|
||||||
rate->count = tries;
|
rate->count = tries;
|
||||||
rate->idx = rix;
|
rate->idx = rix;
|
||||||
@@ -911,15 +888,16 @@ static void ath_rc_ratefind(struct ath_softc *sc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath_rc_update_ht(struct ath_softc *sc,
|
static bool ath_rc_update_per(struct ath_softc *sc,
|
||||||
|
struct ath_rate_table *rate_table,
|
||||||
struct ath_rate_priv *ath_rc_priv,
|
struct ath_rate_priv *ath_rc_priv,
|
||||||
struct ath_tx_info_priv *tx_info_priv,
|
struct ath_tx_info_priv *tx_info_priv,
|
||||||
int tx_rate, int xretries, int retries)
|
int tx_rate, int xretries, int retries,
|
||||||
|
u32 now_msec)
|
||||||
{
|
{
|
||||||
u32 now_msec = jiffies_to_msecs(jiffies);
|
bool state_change = false;
|
||||||
int state_change = 0, rate, count;
|
int count;
|
||||||
u8 last_per;
|
u8 last_per;
|
||||||
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
|
|
||||||
static u32 nretry_to_per_lookup[10] = {
|
static u32 nretry_to_per_lookup[10] = {
|
||||||
100 * 0 / 1,
|
100 * 0 / 1,
|
||||||
100 * 1 / 4,
|
100 * 1 / 4,
|
||||||
@@ -933,24 +911,9 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
100 * 9 / 10
|
100 * 9 / 10
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!ath_rc_priv)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ASSERT(tx_rate >= 0);
|
|
||||||
if (tx_rate < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* To compensate for some imbalance between ctrl and ext. channel */
|
|
||||||
|
|
||||||
if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
|
|
||||||
tx_info_priv->tx.ts_rssi =
|
|
||||||
tx_info_priv->tx.ts_rssi < 3 ? 0 :
|
|
||||||
tx_info_priv->tx.ts_rssi - 3;
|
|
||||||
|
|
||||||
last_per = ath_rc_priv->state[tx_rate].per;
|
last_per = ath_rc_priv->state[tx_rate].per;
|
||||||
|
|
||||||
if (xretries) {
|
if (xretries) {
|
||||||
/* Update the PER. */
|
|
||||||
if (xretries == 1) {
|
if (xretries == 1) {
|
||||||
ath_rc_priv->state[tx_rate].per += 30;
|
ath_rc_priv->state[tx_rate].per += 30;
|
||||||
if (ath_rc_priv->state[tx_rate].per > 100)
|
if (ath_rc_priv->state[tx_rate].per > 100)
|
||||||
@@ -960,11 +923,10 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
count = ARRAY_SIZE(nretry_to_per_lookup);
|
count = ARRAY_SIZE(nretry_to_per_lookup);
|
||||||
if (retries >= count)
|
if (retries >= count)
|
||||||
retries = count - 1;
|
retries = count - 1;
|
||||||
|
|
||||||
/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
|
/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
|
||||||
ath_rc_priv->state[tx_rate].per =
|
ath_rc_priv->state[tx_rate].per =
|
||||||
(u8)(ath_rc_priv->state[tx_rate].per -
|
(u8)(last_per - (last_per >> 3) + (100 >> 3));
|
||||||
(ath_rc_priv->state[tx_rate].per >> 3) +
|
|
||||||
((100) >> 3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* xretries == 1 or 2 */
|
/* xretries == 1 or 2 */
|
||||||
@@ -973,11 +935,10 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
ath_rc_priv->probe_rate = 0;
|
ath_rc_priv->probe_rate = 0;
|
||||||
|
|
||||||
} else { /* xretries == 0 */
|
} else { /* xretries == 0 */
|
||||||
/* Update the PER. */
|
|
||||||
/* Make sure it doesn't index out of array's bounds. */
|
|
||||||
count = ARRAY_SIZE(nretry_to_per_lookup);
|
count = ARRAY_SIZE(nretry_to_per_lookup);
|
||||||
if (retries >= count)
|
if (retries >= count)
|
||||||
retries = count - 1;
|
retries = count - 1;
|
||||||
|
|
||||||
if (tx_info_priv->n_bad_frames) {
|
if (tx_info_priv->n_bad_frames) {
|
||||||
/* new_PER = 7/8*old_PER + 1/8*(currentPER)
|
/* new_PER = 7/8*old_PER + 1/8*(currentPER)
|
||||||
* Assuming that n_frames is not 0. The current PER
|
* Assuming that n_frames is not 0. The current PER
|
||||||
@@ -991,21 +952,20 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
* the above PER. The expression below is a
|
* the above PER. The expression below is a
|
||||||
* simplified version of the sum of these two terms.
|
* simplified version of the sum of these two terms.
|
||||||
*/
|
*/
|
||||||
if (tx_info_priv->n_frames > 0)
|
if (tx_info_priv->n_frames > 0) {
|
||||||
ath_rc_priv->state[tx_rate].per
|
int n_frames, n_bad_frames;
|
||||||
= (u8)
|
u8 cur_per, new_per;
|
||||||
(ath_rc_priv->state[tx_rate].per -
|
|
||||||
(ath_rc_priv->state[tx_rate].per >> 3) +
|
|
||||||
((100*(retries*tx_info_priv->n_frames +
|
|
||||||
tx_info_priv->n_bad_frames) /
|
|
||||||
(tx_info_priv->n_frames *
|
|
||||||
(retries+1))) >> 3));
|
|
||||||
} else {
|
|
||||||
/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
|
|
||||||
|
|
||||||
ath_rc_priv->state[tx_rate].per = (u8)
|
n_bad_frames = retries * tx_info_priv->n_frames +
|
||||||
(ath_rc_priv->state[tx_rate].per -
|
tx_info_priv->n_bad_frames;
|
||||||
(ath_rc_priv->state[tx_rate].per >> 3) +
|
n_frames = tx_info_priv->n_frames * (retries + 1);
|
||||||
|
cur_per = (100 * n_bad_frames / n_frames) >> 3;
|
||||||
|
new_per = (u8)(last_per - (last_per >> 3) + cur_per);
|
||||||
|
ath_rc_priv->state[tx_rate].per = new_per;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ath_rc_priv->state[tx_rate].per =
|
||||||
|
(u8)(last_per - (last_per >> 3) +
|
||||||
(nretry_to_per_lookup[retries] >> 3));
|
(nretry_to_per_lookup[retries] >> 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,7 +978,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
* If we got at most one retry then increase the max rate if
|
* If we got at most one retry then increase the max rate if
|
||||||
* this was a probe. Otherwise, ignore the probe.
|
* this was a probe. Otherwise, ignore the probe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
|
if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
|
||||||
if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
|
if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
|
||||||
tx_info_priv->n_frames) {
|
tx_info_priv->n_frames) {
|
||||||
@@ -1033,7 +992,8 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
} else {
|
} else {
|
||||||
u8 probe_rate = 0;
|
u8 probe_rate = 0;
|
||||||
|
|
||||||
ath_rc_priv->rate_max_phy = ath_rc_priv->probe_rate;
|
ath_rc_priv->rate_max_phy =
|
||||||
|
ath_rc_priv->probe_rate;
|
||||||
probe_rate = ath_rc_priv->probe_rate;
|
probe_rate = ath_rc_priv->probe_rate;
|
||||||
|
|
||||||
if (ath_rc_priv->state[probe_rate].per > 30)
|
if (ath_rc_priv->state[probe_rate].per > 30)
|
||||||
@@ -1047,8 +1007,8 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
* to move up faster if the probes are
|
* to move up faster if the probes are
|
||||||
* succesful.
|
* succesful.
|
||||||
*/
|
*/
|
||||||
ath_rc_priv->probe_time = now_msec -
|
ath_rc_priv->probe_time =
|
||||||
rate_table->probe_interval / 2;
|
now_msec - rate_table->probe_interval / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1064,6 +1024,10 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
*/
|
*/
|
||||||
ath_rc_priv->hw_maxretry_pktcnt = 0;
|
ath_rc_priv->hw_maxretry_pktcnt = 0;
|
||||||
} else {
|
} else {
|
||||||
|
int32_t rssi_ackAvg;
|
||||||
|
int8_t rssi_thres;
|
||||||
|
int8_t rssi_ack_vmin;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It worked with no retries. First ignore bogus (small)
|
* It worked with no retries. First ignore bogus (small)
|
||||||
* rssi_ack values.
|
* rssi_ack values.
|
||||||
@@ -1073,8 +1037,10 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
ath_rc_priv->hw_maxretry_pktcnt++;
|
ath_rc_priv->hw_maxretry_pktcnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx_info_priv->tx.ts_rssi >=
|
if (tx_info_priv->tx.ts_rssi <
|
||||||
rate_table->info[tx_rate].rssi_ack_validmin) {
|
rate_table->info[tx_rate].rssi_ack_validmin)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
/* Average the rssi */
|
/* Average the rssi */
|
||||||
if (tx_rate != ath_rc_priv->rssi_sum_rate) {
|
if (tx_rate != ath_rc_priv->rssi_sum_rate) {
|
||||||
ath_rc_priv->rssi_sum_rate = tx_rate;
|
ath_rc_priv->rssi_sum_rate = tx_rate;
|
||||||
@@ -1085,34 +1051,68 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi;
|
ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi;
|
||||||
ath_rc_priv->rssi_sum_cnt++;
|
ath_rc_priv->rssi_sum_cnt++;
|
||||||
|
|
||||||
if (ath_rc_priv->rssi_sum_cnt > 4) {
|
if (ath_rc_priv->rssi_sum_cnt < 4)
|
||||||
int32_t rssi_ackAvg =
|
goto exit;
|
||||||
|
|
||||||
|
rssi_ackAvg =
|
||||||
(ath_rc_priv->rssi_sum + 2) / 4;
|
(ath_rc_priv->rssi_sum + 2) / 4;
|
||||||
int8_t rssi_thres =
|
rssi_thres =
|
||||||
ath_rc_priv->state[tx_rate].
|
ath_rc_priv->state[tx_rate].rssi_thres;
|
||||||
rssi_thres;
|
rssi_ack_vmin =
|
||||||
int8_t rssi_ack_vmin =
|
rate_table->info[tx_rate].rssi_ack_validmin;
|
||||||
rate_table->info[tx_rate].
|
|
||||||
rssi_ack_validmin;
|
|
||||||
|
|
||||||
ath_rc_priv->rssi_sum =
|
ath_rc_priv->rssi_sum =
|
||||||
ath_rc_priv->rssi_sum_cnt = 0;
|
ath_rc_priv->rssi_sum_cnt = 0;
|
||||||
|
|
||||||
/* Now reduce the current
|
/* Now reduce the current rssi threshold */
|
||||||
* rssi threshold. */
|
|
||||||
if ((rssi_ackAvg < rssi_thres + 2) &&
|
if ((rssi_ackAvg < rssi_thres + 2) &&
|
||||||
(rssi_thres > rssi_ack_vmin)) {
|
(rssi_thres > rssi_ack_vmin)) {
|
||||||
ath_rc_priv->state[tx_rate].
|
ath_rc_priv->state[tx_rate].rssi_thres--;
|
||||||
rssi_thres--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state_change = 1;
|
state_change = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
exit:
|
||||||
|
return state_change;
|
||||||
|
}
|
||||||
|
|
||||||
/* For all cases */
|
/* Update PER, RSSI and whatever else that the code thinks it is doing.
|
||||||
|
If you can make sense of all this, you really need to go out more. */
|
||||||
|
|
||||||
|
static void ath_rc_update_ht(struct ath_softc *sc,
|
||||||
|
struct ath_rate_priv *ath_rc_priv,
|
||||||
|
struct ath_tx_info_priv *tx_info_priv,
|
||||||
|
int tx_rate, int xretries, int retries)
|
||||||
|
{
|
||||||
|
#define CHK_RSSI(rate) \
|
||||||
|
((ath_rc_priv->state[(rate)].rssi_thres + \
|
||||||
|
rate_table->info[(rate)].rssi_ack_deltamin) > \
|
||||||
|
ath_rc_priv->state[(rate)+1].rssi_thres)
|
||||||
|
|
||||||
|
u32 now_msec = jiffies_to_msecs(jiffies);
|
||||||
|
int rate;
|
||||||
|
u8 last_per;
|
||||||
|
bool state_change = false;
|
||||||
|
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
|
||||||
|
int size = ath_rc_priv->rate_table_size;
|
||||||
|
|
||||||
|
if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* To compensate for some imbalance between ctrl and ext. channel */
|
||||||
|
|
||||||
|
if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
|
||||||
|
tx_info_priv->tx.ts_rssi =
|
||||||
|
tx_info_priv->tx.ts_rssi < 3 ? 0 :
|
||||||
|
tx_info_priv->tx.ts_rssi - 3;
|
||||||
|
|
||||||
|
last_per = ath_rc_priv->state[tx_rate].per;
|
||||||
|
|
||||||
|
/* Update PER first */
|
||||||
|
state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
|
||||||
|
tx_info_priv, tx_rate, xretries,
|
||||||
|
retries, now_msec);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this rate looks bad (high PER) then stop using it for
|
* If this rate looks bad (high PER) then stop using it for
|
||||||
@@ -1122,7 +1122,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
rate_table->info[tx_rate].ratekbps <=
|
rate_table->info[tx_rate].ratekbps <=
|
||||||
rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
|
rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
|
||||||
ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
|
ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
|
||||||
(u8) tx_rate, &ath_rc_priv->rate_max_phy);
|
(u8)tx_rate, &ath_rc_priv->rate_max_phy);
|
||||||
|
|
||||||
/* Don't probe for a little while. */
|
/* Don't probe for a little while. */
|
||||||
ath_rc_priv->probe_time = now_msec;
|
ath_rc_priv->probe_time = now_msec;
|
||||||
@@ -1136,20 +1136,15 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
* made to keep the rssi thresholds monotonically
|
* made to keep the rssi thresholds monotonically
|
||||||
* increasing between the CCK and OFDM rates.)
|
* increasing between the CCK and OFDM rates.)
|
||||||
*/
|
*/
|
||||||
for (rate = tx_rate; rate <
|
for (rate = tx_rate; rate < size - 1; rate++) {
|
||||||
ath_rc_priv->rate_table_size - 1; rate++) {
|
|
||||||
if (rate_table->info[rate+1].phy !=
|
if (rate_table->info[rate+1].phy !=
|
||||||
rate_table->info[tx_rate].phy)
|
rate_table->info[tx_rate].phy)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (ath_rc_priv->state[rate].rssi_thres +
|
if (CHK_RSSI(rate)) {
|
||||||
rate_table->info[rate].rssi_ack_deltamin >
|
|
||||||
ath_rc_priv->state[rate+1].rssi_thres) {
|
|
||||||
ath_rc_priv->state[rate+1].rssi_thres =
|
ath_rc_priv->state[rate+1].rssi_thres =
|
||||||
ath_rc_priv->state[rate].
|
ath_rc_priv->state[rate].rssi_thres +
|
||||||
rssi_thres +
|
rate_table->info[rate].rssi_ack_deltamin;
|
||||||
rate_table->info[rate].
|
|
||||||
rssi_ack_deltamin;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1159,27 +1154,20 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
rate_table->info[tx_rate].phy)
|
rate_table->info[tx_rate].phy)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (ath_rc_priv->state[rate].rssi_thres +
|
if (CHK_RSSI(rate)) {
|
||||||
rate_table->info[rate].rssi_ack_deltamin >
|
|
||||||
ath_rc_priv->state[rate+1].rssi_thres) {
|
|
||||||
if (ath_rc_priv->state[rate+1].rssi_thres <
|
if (ath_rc_priv->state[rate+1].rssi_thres <
|
||||||
rate_table->info[rate].
|
rate_table->info[rate].rssi_ack_deltamin)
|
||||||
rssi_ack_deltamin)
|
|
||||||
ath_rc_priv->state[rate].rssi_thres = 0;
|
ath_rc_priv->state[rate].rssi_thres = 0;
|
||||||
else {
|
else {
|
||||||
ath_rc_priv->state[rate].rssi_thres =
|
ath_rc_priv->state[rate].rssi_thres =
|
||||||
ath_rc_priv->state[rate+1].
|
ath_rc_priv->state[rate+1].rssi_thres -
|
||||||
rssi_thres -
|
rate_table->info[rate].rssi_ack_deltamin;
|
||||||
rate_table->info[rate].
|
|
||||||
rssi_ack_deltamin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ath_rc_priv->state[rate].rssi_thres <
|
if (ath_rc_priv->state[rate].rssi_thres <
|
||||||
rate_table->info[rate].
|
rate_table->info[rate].rssi_ack_validmin) {
|
||||||
rssi_ack_validmin) {
|
|
||||||
ath_rc_priv->state[rate].rssi_thres =
|
ath_rc_priv->state[rate].rssi_thres =
|
||||||
rate_table->info[rate].
|
rate_table->info[rate].rssi_ack_validmin;
|
||||||
rssi_ack_validmin;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1202,8 +1190,9 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Maintain monotonicity for rates above the current rate */
|
/* Maintain monotonicity for rates above the current rate */
|
||||||
for (rate = tx_rate; rate < ath_rc_priv->rate_table_size - 1; rate++) {
|
for (rate = tx_rate; rate < size - 1; rate++) {
|
||||||
if (ath_rc_priv->state[rate+1].per < ath_rc_priv->state[rate].per)
|
if (ath_rc_priv->state[rate+1].per <
|
||||||
|
ath_rc_priv->state[rate].per)
|
||||||
ath_rc_priv->state[rate+1].per =
|
ath_rc_priv->state[rate+1].per =
|
||||||
ath_rc_priv->state[rate].per;
|
ath_rc_priv->state[rate].per;
|
||||||
}
|
}
|
||||||
@@ -1213,7 +1202,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
if (now_msec - ath_rc_priv->rssi_down_time >=
|
if (now_msec - ath_rc_priv->rssi_down_time >=
|
||||||
rate_table->rssi_reduce_interval) {
|
rate_table->rssi_reduce_interval) {
|
||||||
|
|
||||||
for (rate = 0; rate < ath_rc_priv->rate_table_size; rate++) {
|
for (rate = 0; rate < size; rate++) {
|
||||||
if (ath_rc_priv->state[rate].rssi_thres >
|
if (ath_rc_priv->state[rate].rssi_thres >
|
||||||
rate_table->info[rate].rssi_ack_validmin)
|
rate_table->info[rate].rssi_ack_validmin)
|
||||||
ath_rc_priv->state[rate].rssi_thres -= 1;
|
ath_rc_priv->state[rate].rssi_thres -= 1;
|
||||||
@@ -1225,13 +1214,33 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||||||
* and PER (different for CCK and OFDM). */
|
* and PER (different for CCK and OFDM). */
|
||||||
if (now_msec - ath_rc_priv->per_down_time >=
|
if (now_msec - ath_rc_priv->per_down_time >=
|
||||||
rate_table->rssi_reduce_interval) {
|
rate_table->rssi_reduce_interval) {
|
||||||
for (rate = 0; rate < ath_rc_priv->rate_table_size; rate++) {
|
for (rate = 0; rate < size; rate++) {
|
||||||
ath_rc_priv->state[rate].per =
|
ath_rc_priv->state[rate].per =
|
||||||
7 * ath_rc_priv->state[rate].per / 8;
|
7 * ath_rc_priv->state[rate].per / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
ath_rc_priv->per_down_time = now_msec;
|
ath_rc_priv->per_down_time = now_msec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef CHK_RSSI
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ath_rc_get_rateindex(struct ath_rate_table *rate_table,
|
||||||
|
struct ieee80211_tx_rate *rate)
|
||||||
|
{
|
||||||
|
int rix;
|
||||||
|
|
||||||
|
if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
|
||||||
|
(rate->flags & IEEE80211_TX_RC_SHORT_GI))
|
||||||
|
rix = rate_table->info[rate->idx].ht_index;
|
||||||
|
else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
|
||||||
|
rix = rate_table->info[rate->idx].sgi_index;
|
||||||
|
else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
|
||||||
|
rix = rate_table->info[rate->idx].cw40index;
|
||||||
|
else
|
||||||
|
rix = rate_table->info[rate->idx].base_index;
|
||||||
|
|
||||||
|
return rix;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath_rc_tx_status(struct ath_softc *sc,
|
static void ath_rc_tx_status(struct ath_softc *sc,
|
||||||
@@ -1243,7 +1252,7 @@ static void ath_rc_tx_status(struct ath_softc *sc,
|
|||||||
struct ath_rate_table *rate_table;
|
struct ath_rate_table *rate_table;
|
||||||
struct ieee80211_tx_rate *rates = tx_info->status.rates;
|
struct ieee80211_tx_rate *rates = tx_info->status.rates;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u32 series = 0, rix;
|
u32 i = 0, rix;
|
||||||
|
|
||||||
rate_table = sc->hw_rate_table[sc->sc_curmode];
|
rate_table = sc->hw_rate_table[sc->sc_curmode];
|
||||||
|
|
||||||
@@ -1253,32 +1262,22 @@ static void ath_rc_tx_status(struct ath_softc *sc,
|
|||||||
*/
|
*/
|
||||||
if (final_ts_idx != 0) {
|
if (final_ts_idx != 0) {
|
||||||
/* Process intermediate rates that failed.*/
|
/* Process intermediate rates that failed.*/
|
||||||
for (series = 0; series < final_ts_idx ; series++) {
|
for (i = 0; i < final_ts_idx ; i++) {
|
||||||
if (rates[series].count != 0 && (rates[series].idx >= 0)) {
|
if (rates[i].count != 0 && (rates[i].idx >= 0)) {
|
||||||
flags = rates[series].flags;
|
flags = rates[i].flags;
|
||||||
|
|
||||||
/* If HT40 and we have switched mode from
|
/* If HT40 and we have switched mode from
|
||||||
* 40 to 20 => don't update */
|
* 40 to 20 => don't update */
|
||||||
|
|
||||||
if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
|
if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
|
||||||
(ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG))
|
(ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
|
rix = ath_rc_get_rateindex(rate_table, &rates[i]);
|
||||||
(flags & IEEE80211_TX_RC_SHORT_GI))
|
|
||||||
rix = rate_table->info[
|
|
||||||
rates[series].idx].ht_index;
|
|
||||||
else if (flags & IEEE80211_TX_RC_SHORT_GI)
|
|
||||||
rix = rate_table->info[
|
|
||||||
rates[series].idx].sgi_index;
|
|
||||||
else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
|
|
||||||
rix = rate_table->info[
|
|
||||||
rates[series].idx].cw40index;
|
|
||||||
else
|
|
||||||
rix = rate_table->info[
|
|
||||||
rates[series].idx].base_index;
|
|
||||||
ath_rc_update_ht(sc, ath_rc_priv,
|
ath_rc_update_ht(sc, ath_rc_priv,
|
||||||
tx_info_priv, rix,
|
tx_info_priv, rix,
|
||||||
xretries ? 1 : 2,
|
xretries ? 1 : 2,
|
||||||
rates[series].count);
|
rates[i].count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1292,22 +1291,15 @@ static void ath_rc_tx_status(struct ath_softc *sc,
|
|||||||
xretries = 2;
|
xretries = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = rates[series].flags;
|
flags = rates[i].flags;
|
||||||
|
|
||||||
/* If HT40 and we have switched mode from 40 to 20 => don't update */
|
/* If HT40 and we have switched mode from 40 to 20 => don't update */
|
||||||
if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
|
if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
|
||||||
(ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) {
|
(ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && (flags & IEEE80211_TX_RC_SHORT_GI))
|
rix = ath_rc_get_rateindex(rate_table, &rates[i]);
|
||||||
rix = rate_table->info[rates[series].idx].ht_index;
|
|
||||||
else if (flags & IEEE80211_TX_RC_SHORT_GI)
|
|
||||||
rix = rate_table->info[rates[series].idx].sgi_index;
|
|
||||||
else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
|
|
||||||
rix = rate_table->info[rates[series].idx].cw40index;
|
|
||||||
else
|
|
||||||
rix = rate_table->info[rates[series].idx].base_index;
|
|
||||||
|
|
||||||
ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
|
ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
|
||||||
xretries, long_retry);
|
xretries, long_retry);
|
||||||
}
|
}
|
||||||
@@ -1362,14 +1354,14 @@ static void ath_rc_init(struct ath_softc *sc,
|
|||||||
|
|
||||||
if (!rateset->rs_nrates) {
|
if (!rateset->rs_nrates) {
|
||||||
/* No working rate, just initialize valid rates */
|
/* No working rate, just initialize valid rates */
|
||||||
hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table,
|
hi = ath_rc_init_validrates(ath_rc_priv, rate_table,
|
||||||
ath_rc_priv->ht_cap);
|
ath_rc_priv->ht_cap);
|
||||||
} else {
|
} else {
|
||||||
/* Use intersection of working rates and valid rates */
|
/* Use intersection of working rates and valid rates */
|
||||||
hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table,
|
hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table,
|
||||||
rateset, ath_rc_priv->ht_cap);
|
rateset, ath_rc_priv->ht_cap);
|
||||||
if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
|
if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
|
||||||
hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv,
|
hthi = ath_rc_setvalid_htrates(ath_rc_priv,
|
||||||
rate_table,
|
rate_table,
|
||||||
ht_mcs,
|
ht_mcs,
|
||||||
ath_rc_priv->ht_cap);
|
ath_rc_priv->ht_cap);
|
||||||
|
@@ -27,6 +27,11 @@ struct ath_softc;
|
|||||||
#define RATE_TABLE_SIZE 64
|
#define RATE_TABLE_SIZE 64
|
||||||
#define MAX_TX_RATE_PHY 48
|
#define MAX_TX_RATE_PHY 48
|
||||||
|
|
||||||
|
/* VALID_ALL - valid for 20/40/Legacy,
|
||||||
|
* VALID - Legacy only,
|
||||||
|
* VALID_20 - HT 20 only,
|
||||||
|
* VALID_40 - HT 40 only */
|
||||||
|
|
||||||
#define INVALID 0x0
|
#define INVALID 0x0
|
||||||
#define VALID 0x1
|
#define VALID 0x1
|
||||||
#define VALID_20 0x2
|
#define VALID_20 0x2
|
||||||
|
Reference in New Issue
Block a user