A few more small things, nothing really stands out:
* minstrel improvements from Felix * a TX aggregation simplification * some additional capabilities for hwsim * minor cleanups & docs updates -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl2gQp8ACgkQB8qZga/f l8T5kA//Yo07t93OespsNwJZXWx7l/WWBtIydnTAk9hNXDV4kd6oLgN0oadqpx7g 5bryCRqmS4vx2IjiEQiSK08JqmhpruQSXYe8oixVVCOknw2pfkK6lr+OHCqJO11A iWu5Nz7bTl4pfSO0XIfWk1STUjNuXWCTUgbLSwU4oaoqk8oib2VeV1QdXX0hvgXF gSlToWQqliI/c6HS69iUJGRqXZCMO7GPWE9Sqj8cvmeAFXWQz9zcan6Fcd2XJyLq qJxNbxGD0JQ6vdbg2bFnio8PlwYMJ7ohrRDds8euYzViVtyTVZ6WtD9/gKB6UGVe RS5NEsmZLISCrQbV8nK/q0G/mBdNNegj4ezUkWxMvuYDEvl83Xniyz5CoAC++9mp 0M0//+NgwoVqDvaoV0s+TZBYv5arJyeUCY9kkmPCFFVV6cvmXfRFpn9yU95he2Eb duY5P+uKNlFU+sYVh1d6QC26mEAIa0y4qZszp3HurVWXe/aG/fLumW2USAOdqDOw 9HF9vOqGc3FRZTX1l15F+5nPn9gMyMJJGqOeT4oS1mQJT/KdzQCGLmhQ+IR+00Un zF6QsfCCtbuO5xLErqoARa7qKzddDxgkEBbdmQmjUwdyzAxSxZxGDBLLcpZ0OQwo Kxx7ELz97f55unLbByDrFMoZvEXaCeGcbZeTJWGvDRElw/BhRJU= =IJ7D -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-net-next-2019-10-11' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== A few more small things, nothing really stands out: * minstrel improvements from Felix * a TX aggregation simplification * some additional capabilities for hwsim * minor cleanups & docs updates ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
7e0d15ee0d
|
@ -1674,7 +1674,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
|
ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||||
|
|
|
@ -1921,7 +1921,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
||||||
ath9k_ps_wakeup(sc);
|
ath9k_ps_wakeup(sc);
|
||||||
ret = ath_tx_aggr_start(sc, sta, tid, ssn);
|
ret = ath_tx_aggr_start(sc, sta, tid, ssn);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
ath9k_ps_restore(sc);
|
ath9k_ps_restore(sc);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||||
|
|
|
@ -1449,8 +1449,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
|
||||||
rcu_assign_pointer(sta_info->agg[tid], tid_info);
|
rcu_assign_pointer(sta_info->agg[tid], tid_info);
|
||||||
spin_unlock_bh(&ar->tx_ampdu_list_lock);
|
spin_unlock_bh(&ar->tx_ampdu_list_lock);
|
||||||
|
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
|
||||||
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||||
|
|
|
@ -1084,6 +1084,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||||
enum ieee80211_ampdu_mlme_action action = params->action;
|
enum ieee80211_ampdu_mlme_action action = params->action;
|
||||||
u16 tid = params->tid;
|
u16 tid = params->tid;
|
||||||
u16 *ssn = ¶ms->ssn;
|
u16 *ssn = ¶ms->ssn;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
|
||||||
action, tid);
|
action, tid);
|
||||||
|
@ -1106,7 +1107,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||||
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
|
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
|
||||||
spin_unlock_bh(&sta_priv->ampdu_lock);
|
spin_unlock_bh(&sta_priv->ampdu_lock);
|
||||||
|
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||||
spin_lock_bh(&sta_priv->ampdu_lock);
|
spin_lock_bh(&sta_priv->ampdu_lock);
|
||||||
|
@ -1131,7 +1132,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
mutex_unlock(&wcn->conf_mutex);
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ieee80211_ops wcn36xx_ops = {
|
static const struct ieee80211_ops wcn36xx_ops = {
|
||||||
|
|
|
@ -850,8 +850,7 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
|
||||||
"START: tid %d is not agg\'able\n", tid);
|
"START: tid %d is not agg\'able\n", tid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
|
||||||
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||||
|
|
|
@ -2265,7 +2265,7 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
|
||||||
if (tid_data->tfds_in_queue == 0) {
|
if (tid_data->tfds_in_queue == 0) {
|
||||||
D_HT("HW queue is empty\n");
|
D_HT("HW queue is empty\n");
|
||||||
tid_data->agg.state = IL_AGG_ON;
|
tid_data->agg.state = IL_AGG_ON;
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
} else {
|
} else {
|
||||||
D_HT("HW queue is NOT empty: %d packets in HW queue\n",
|
D_HT("HW queue is NOT empty: %d packets in HW queue\n",
|
||||||
tid_data->tfds_in_queue);
|
tid_data->tfds_in_queue);
|
||||||
|
|
|
@ -621,7 +621,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||||
IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n",
|
IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n",
|
||||||
tid_data->agg.ssn);
|
tid_data->agg.ssn);
|
||||||
tid_data->agg.state = IWL_AGG_STARTING;
|
tid_data->agg.state = IWL_AGG_STARTING;
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
} else {
|
} else {
|
||||||
IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
|
IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
|
||||||
"next_reclaimed = %d\n",
|
"next_reclaimed = %d\n",
|
||||||
|
|
|
@ -2818,13 +2818,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
|
|
||||||
if (normalized_ssn == tid_data->next_reclaimed) {
|
if (normalized_ssn == tid_data->next_reclaimed) {
|
||||||
tid_data->state = IWL_AGG_STARTING;
|
tid_data->state = IWL_AGG_STARTING;
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
} else {
|
} else {
|
||||||
tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA;
|
tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA;
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock_bh(&mvmsta->lock);
|
spin_unlock_bh(&mvmsta->lock);
|
||||||
|
|
||||||
|
|
|
@ -148,23 +148,25 @@ static const char *hwsim_alpha2s[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ieee80211_regdomain hwsim_world_regdom_custom_01 = {
|
static const struct ieee80211_regdomain hwsim_world_regdom_custom_01 = {
|
||||||
.n_reg_rules = 4,
|
.n_reg_rules = 5,
|
||||||
.alpha2 = "99",
|
.alpha2 = "99",
|
||||||
.reg_rules = {
|
.reg_rules = {
|
||||||
REG_RULE(2412-10, 2462+10, 40, 0, 20, 0),
|
REG_RULE(2412-10, 2462+10, 40, 0, 20, 0),
|
||||||
REG_RULE(2484-10, 2484+10, 40, 0, 20, 0),
|
REG_RULE(2484-10, 2484+10, 40, 0, 20, 0),
|
||||||
REG_RULE(5150-10, 5240+10, 40, 0, 30, 0),
|
REG_RULE(5150-10, 5240+10, 40, 0, 30, 0),
|
||||||
REG_RULE(5745-10, 5825+10, 40, 0, 30, 0),
|
REG_RULE(5745-10, 5825+10, 40, 0, 30, 0),
|
||||||
|
REG_RULE(5855-10, 5925+10, 40, 0, 33, 0),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = {
|
static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = {
|
||||||
.n_reg_rules = 2,
|
.n_reg_rules = 3,
|
||||||
.alpha2 = "99",
|
.alpha2 = "99",
|
||||||
.reg_rules = {
|
.reg_rules = {
|
||||||
REG_RULE(2412-10, 2462+10, 40, 0, 20, 0),
|
REG_RULE(2412-10, 2462+10, 40, 0, 20, 0),
|
||||||
REG_RULE(5725-10, 5850+10, 40, 0, 30,
|
REG_RULE(5725-10, 5850+10, 40, 0, 30,
|
||||||
NL80211_RRF_NO_IR),
|
NL80211_RRF_NO_IR),
|
||||||
|
REG_RULE(5855-10, 5925+10, 40, 0, 33, 0),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -354,6 +356,24 @@ static const struct ieee80211_channel hwsim_channels_5ghz[] = {
|
||||||
CHAN5G(5805), /* Channel 161 */
|
CHAN5G(5805), /* Channel 161 */
|
||||||
CHAN5G(5825), /* Channel 165 */
|
CHAN5G(5825), /* Channel 165 */
|
||||||
CHAN5G(5845), /* Channel 169 */
|
CHAN5G(5845), /* Channel 169 */
|
||||||
|
|
||||||
|
CHAN5G(5855), /* Channel 171 */
|
||||||
|
CHAN5G(5860), /* Channel 172 */
|
||||||
|
CHAN5G(5865), /* Channel 173 */
|
||||||
|
CHAN5G(5870), /* Channel 174 */
|
||||||
|
|
||||||
|
CHAN5G(5875), /* Channel 175 */
|
||||||
|
CHAN5G(5880), /* Channel 176 */
|
||||||
|
CHAN5G(5885), /* Channel 177 */
|
||||||
|
CHAN5G(5890), /* Channel 178 */
|
||||||
|
CHAN5G(5895), /* Channel 179 */
|
||||||
|
CHAN5G(5900), /* Channel 180 */
|
||||||
|
CHAN5G(5905), /* Channel 181 */
|
||||||
|
|
||||||
|
CHAN5G(5910), /* Channel 182 */
|
||||||
|
CHAN5G(5915), /* Channel 183 */
|
||||||
|
CHAN5G(5920), /* Channel 184 */
|
||||||
|
CHAN5G(5925), /* Channel 185 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ieee80211_rate hwsim_rates[] = {
|
static const struct ieee80211_rate hwsim_rates[] = {
|
||||||
|
@ -1550,7 +1570,8 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
|
||||||
|
|
||||||
if (vif->type != NL80211_IFTYPE_AP &&
|
if (vif->type != NL80211_IFTYPE_AP &&
|
||||||
vif->type != NL80211_IFTYPE_MESH_POINT &&
|
vif->type != NL80211_IFTYPE_MESH_POINT &&
|
||||||
vif->type != NL80211_IFTYPE_ADHOC)
|
vif->type != NL80211_IFTYPE_ADHOC &&
|
||||||
|
vif->type != NL80211_IFTYPE_OCB)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
skb = ieee80211_beacon_get(hw, vif);
|
skb = ieee80211_beacon_get(hw, vif);
|
||||||
|
@ -1604,6 +1625,8 @@ mac80211_hwsim_beacon(struct hrtimer *timer)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const hwsim_chanwidths[] = {
|
static const char * const hwsim_chanwidths[] = {
|
||||||
|
[NL80211_CHAN_WIDTH_5] = "ht5",
|
||||||
|
[NL80211_CHAN_WIDTH_10] = "ht10",
|
||||||
[NL80211_CHAN_WIDTH_20_NOHT] = "noht",
|
[NL80211_CHAN_WIDTH_20_NOHT] = "noht",
|
||||||
[NL80211_CHAN_WIDTH_20] = "ht20",
|
[NL80211_CHAN_WIDTH_20] = "ht20",
|
||||||
[NL80211_CHAN_WIDTH_40] = "ht40",
|
[NL80211_CHAN_WIDTH_40] = "ht40",
|
||||||
|
@ -1979,8 +2002,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||||
|
@ -2723,7 +2745,8 @@ static void mac80211_hwsim_he_capab(struct ieee80211_supported_band *sband)
|
||||||
BIT(NL80211_IFTYPE_P2P_CLIENT) | \
|
BIT(NL80211_IFTYPE_P2P_CLIENT) | \
|
||||||
BIT(NL80211_IFTYPE_P2P_GO) | \
|
BIT(NL80211_IFTYPE_P2P_GO) | \
|
||||||
BIT(NL80211_IFTYPE_ADHOC) | \
|
BIT(NL80211_IFTYPE_ADHOC) | \
|
||||||
BIT(NL80211_IFTYPE_MESH_POINT))
|
BIT(NL80211_IFTYPE_MESH_POINT) | \
|
||||||
|
BIT(NL80211_IFTYPE_OCB))
|
||||||
|
|
||||||
static int mac80211_hwsim_new_radio(struct genl_info *info,
|
static int mac80211_hwsim_new_radio(struct genl_info *info,
|
||||||
struct hwsim_new_radio_params *param)
|
struct hwsim_new_radio_params *param)
|
||||||
|
@ -2847,6 +2870,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
||||||
} else {
|
} else {
|
||||||
data->if_combination.num_different_channels = 1;
|
data->if_combination.num_different_channels = 1;
|
||||||
data->if_combination.radar_detect_widths =
|
data->if_combination.radar_detect_widths =
|
||||||
|
BIT(NL80211_CHAN_WIDTH_5) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_10) |
|
||||||
BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||||
BIT(NL80211_CHAN_WIDTH_20) |
|
BIT(NL80211_CHAN_WIDTH_20) |
|
||||||
BIT(NL80211_CHAN_WIDTH_40) |
|
BIT(NL80211_CHAN_WIDTH_40) |
|
||||||
|
|
|
@ -5520,7 +5520,7 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
rc = -EBUSY;
|
rc = -EBUSY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
|
rc = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||||
|
|
|
@ -582,8 +582,7 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
|
mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
mtxq->aggr = false;
|
mtxq->aggr = false;
|
||||||
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1);
|
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1);
|
||||||
|
|
|
@ -477,8 +477,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
|
mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
mtxq->aggr = false;
|
mtxq->aggr = false;
|
||||||
mt7615_mcu_set_tx_ba(dev, params, 0);
|
mt7615_mcu_set_tx_ba(dev, params, 0);
|
||||||
|
|
|
@ -393,8 +393,7 @@ int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
|
mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
mtxq->aggr = false;
|
mtxq->aggr = false;
|
||||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||||
|
|
|
@ -372,8 +372,7 @@ mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
msta->agg_ssn[tid] = ssn << 4;
|
msta->agg_ssn[tid] = ssn << 4;
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -10476,7 +10476,7 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
* when the hw reorders frames due to aggregation.
|
* when the hw reorders frames due to aggregation.
|
||||||
*/
|
*/
|
||||||
if (sta_priv->wcid > WCID_END)
|
if (sta_priv->wcid > WCID_END)
|
||||||
return 1;
|
return -ENOSPC;
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case IEEE80211_AMPDU_RX_START:
|
case IEEE80211_AMPDU_RX_START:
|
||||||
|
@ -10489,7 +10489,7 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||||
|
|
|
@ -1776,8 +1776,7 @@ int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
|
|
||||||
tid_data->agg.agg_state = RTL_AGG_START;
|
tid_data->agg.agg_state = RTL_AGG_START;
|
||||||
|
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
|
|
|
@ -437,8 +437,7 @@ static int rtw_ops_ampdu_action(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
switch (params->action) {
|
switch (params->action) {
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
break;
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||||
|
|
|
@ -1140,8 +1140,7 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
|
||||||
else if ((vif->type == NL80211_IFTYPE_AP) ||
|
else if ((vif->type == NL80211_IFTYPE_AP) ||
|
||||||
(vif->type == NL80211_IFTYPE_P2P_GO))
|
(vif->type == NL80211_IFTYPE_P2P_GO))
|
||||||
rsta->seq_start[tid] = seq_no;
|
rsta->seq_start[tid] = seq_no;
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
status = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||||
status = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
|
|
|
@ -3095,7 +3095,9 @@ enum ieee80211_filter_flags {
|
||||||
*
|
*
|
||||||
* @IEEE80211_AMPDU_RX_START: start RX aggregation
|
* @IEEE80211_AMPDU_RX_START: start RX aggregation
|
||||||
* @IEEE80211_AMPDU_RX_STOP: stop RX aggregation
|
* @IEEE80211_AMPDU_RX_STOP: stop RX aggregation
|
||||||
* @IEEE80211_AMPDU_TX_START: start TX aggregation
|
* @IEEE80211_AMPDU_TX_START: start TX aggregation, the driver must either
|
||||||
|
* call ieee80211_start_tx_ba_cb_irqsafe() or return the special
|
||||||
|
* status %IEEE80211_AMPDU_TX_START_IMMEDIATE.
|
||||||
* @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational
|
* @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational
|
||||||
* @IEEE80211_AMPDU_TX_STOP_CONT: stop TX aggregation but continue transmitting
|
* @IEEE80211_AMPDU_TX_STOP_CONT: stop TX aggregation but continue transmitting
|
||||||
* queued packets, now unaggregated. After all packets are transmitted the
|
* queued packets, now unaggregated. After all packets are transmitted the
|
||||||
|
@ -3119,6 +3121,8 @@ enum ieee80211_ampdu_mlme_action {
|
||||||
IEEE80211_AMPDU_TX_OPERATIONAL,
|
IEEE80211_AMPDU_TX_OPERATIONAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define IEEE80211_AMPDU_TX_START_IMMEDIATE 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ieee80211_ampdu_params - AMPDU action parameters
|
* struct ieee80211_ampdu_params - AMPDU action parameters
|
||||||
*
|
*
|
||||||
|
@ -3896,7 +3900,10 @@ struct ieee80211_ops {
|
||||||
*
|
*
|
||||||
* Even ``189`` would be wrong since 1 could be lost again.
|
* Even ``189`` would be wrong since 1 could be lost again.
|
||||||
*
|
*
|
||||||
* Returns a negative error code on failure.
|
* Returns a negative error code on failure. The driver may return
|
||||||
|
* %IEEE80211_AMPDU_TX_START_IMMEDIATE for %IEEE80211_AMPDU_TX_START
|
||||||
|
* if the session can start immediately.
|
||||||
|
*
|
||||||
* The callback can sleep.
|
* The callback can sleep.
|
||||||
*/
|
*/
|
||||||
int (*ampdu_action)(struct ieee80211_hw *hw,
|
int (*ampdu_action)(struct ieee80211_hw *hw,
|
||||||
|
|
|
@ -571,6 +571,14 @@
|
||||||
* set of BSSID,frequency parameters is used (i.e., either the enforcing
|
* set of BSSID,frequency parameters is used (i.e., either the enforcing
|
||||||
* %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict
|
* %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict
|
||||||
* %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT).
|
* %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT).
|
||||||
|
* Driver shall not modify the IEs specified through %NL80211_ATTR_IE if
|
||||||
|
* %NL80211_ATTR_MAC is included. However, if %NL80211_ATTR_MAC_HINT is
|
||||||
|
* included, these IEs through %NL80211_ATTR_IE are specified by the user
|
||||||
|
* space based on the best possible BSS selected. Thus, if the driver ends
|
||||||
|
* up selecting a different BSS, it can modify these IEs accordingly (e.g.
|
||||||
|
* userspace asks the driver to perform PMKSA caching with BSS1 and the
|
||||||
|
* driver ends up selecting BSS2 with different PMKSA cache entry; RSNIE
|
||||||
|
* has to get updated with the apt PMKID).
|
||||||
* %NL80211_ATTR_PREV_BSSID can be used to request a reassociation within
|
* %NL80211_ATTR_PREV_BSSID can be used to request a reassociation within
|
||||||
* the ESS in case the device is already associated and an association with
|
* the ESS in case the device is already associated and an association with
|
||||||
* a different BSS is desired.
|
* a different BSS is desired.
|
||||||
|
|
|
@ -485,7 +485,14 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
||||||
|
|
||||||
params.ssn = sta->tid_seq[tid] >> 4;
|
params.ssn = sta->tid_seq[tid] >> 4;
|
||||||
ret = drv_ampdu_action(local, sdata, ¶ms);
|
ret = drv_ampdu_action(local, sdata, ¶ms);
|
||||||
if (ret) {
|
if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
|
||||||
|
/*
|
||||||
|
* We didn't send the request yet, so don't need to check
|
||||||
|
* here if we already got a response, just mark as driver
|
||||||
|
* ready immediately.
|
||||||
|
*/
|
||||||
|
set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
|
||||||
|
} else if (ret) {
|
||||||
ht_dbg(sdata,
|
ht_dbg(sdata,
|
||||||
"BA request denied - HW unavailable for %pM tid %d\n",
|
"BA request denied - HW unavailable for %pM tid %d\n",
|
||||||
sta->sta.addr, tid);
|
sta->sta.addr, tid);
|
||||||
|
|
|
@ -538,7 +538,6 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
|
||||||
{
|
{
|
||||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||||
struct cfg80211_bss *cbss;
|
struct cfg80211_bss *cbss;
|
||||||
int err, changed = 0;
|
|
||||||
|
|
||||||
sdata_assert_lock(sdata);
|
sdata_assert_lock(sdata);
|
||||||
|
|
||||||
|
@ -560,13 +559,7 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
|
||||||
ifibss->chandef = sdata->csa_chandef;
|
ifibss->chandef = sdata->csa_chandef;
|
||||||
|
|
||||||
/* generate the beacon */
|
/* generate the beacon */
|
||||||
err = ieee80211_ibss_csa_beacon(sdata, NULL);
|
return ieee80211_ibss_csa_beacon(sdata, NULL);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
changed |= err;
|
|
||||||
|
|
||||||
return changed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata)
|
void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata)
|
||||||
|
|
|
@ -70,7 +70,7 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return current EMWA throughput */
|
/* return current EMWA throughput */
|
||||||
int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma)
|
int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg)
|
||||||
{
|
{
|
||||||
int usecs;
|
int usecs;
|
||||||
|
|
||||||
|
@ -79,13 +79,13 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma)
|
||||||
usecs = 1000000;
|
usecs = 1000000;
|
||||||
|
|
||||||
/* reset thr. below 10% success */
|
/* reset thr. below 10% success */
|
||||||
if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100))
|
if (mr->stats.prob_avg < MINSTREL_FRAC(10, 100))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (prob_ewma > MINSTREL_FRAC(90, 100))
|
if (prob_avg > MINSTREL_FRAC(90, 100))
|
||||||
return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs));
|
return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs));
|
||||||
else
|
else
|
||||||
return MINSTREL_TRUNC(100000 * (prob_ewma / usecs));
|
return MINSTREL_TRUNC(100000 * (prob_avg / usecs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find & sort topmost throughput rates */
|
/* find & sort topmost throughput rates */
|
||||||
|
@ -98,8 +98,8 @@ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
|
||||||
|
|
||||||
for (j = MAX_THR_RATES; j > 0; --j) {
|
for (j = MAX_THR_RATES; j > 0; --j) {
|
||||||
tmp_mrs = &mi->r[tp_list[j - 1]].stats;
|
tmp_mrs = &mi->r[tp_list[j - 1]].stats;
|
||||||
if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <=
|
if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_avg) <=
|
||||||
minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))
|
minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_avg))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,20 +157,24 @@ minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
|
||||||
* Recalculate statistics and counters of a given rate
|
* Recalculate statistics and counters of a given rate
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
|
minstrel_calc_rate_stats(struct minstrel_priv *mp,
|
||||||
|
struct minstrel_rate_stats *mrs)
|
||||||
{
|
{
|
||||||
unsigned int cur_prob;
|
unsigned int cur_prob;
|
||||||
|
|
||||||
if (unlikely(mrs->attempts > 0)) {
|
if (unlikely(mrs->attempts > 0)) {
|
||||||
mrs->sample_skipped = 0;
|
mrs->sample_skipped = 0;
|
||||||
cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
|
cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
|
||||||
if (unlikely(!mrs->att_hist)) {
|
if (mp->new_avg) {
|
||||||
mrs->prob_ewma = cur_prob;
|
minstrel_filter_avg_add(&mrs->prob_avg,
|
||||||
|
&mrs->prob_avg_1, cur_prob);
|
||||||
|
} else if (unlikely(!mrs->att_hist)) {
|
||||||
|
mrs->prob_avg = cur_prob;
|
||||||
} else {
|
} else {
|
||||||
/*update exponential weighted moving avarage */
|
/*update exponential weighted moving avarage */
|
||||||
mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
|
mrs->prob_avg = minstrel_ewma(mrs->prob_avg,
|
||||||
cur_prob,
|
cur_prob,
|
||||||
EWMA_LEVEL);
|
EWMA_LEVEL);
|
||||||
}
|
}
|
||||||
mrs->att_hist += mrs->attempts;
|
mrs->att_hist += mrs->attempts;
|
||||||
mrs->succ_hist += mrs->success;
|
mrs->succ_hist += mrs->success;
|
||||||
|
@ -200,12 +204,12 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
|
||||||
struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats;
|
struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats;
|
||||||
|
|
||||||
/* Update statistics of success probability per rate */
|
/* Update statistics of success probability per rate */
|
||||||
minstrel_calc_rate_stats(mrs);
|
minstrel_calc_rate_stats(mp, mrs);
|
||||||
|
|
||||||
/* Sample less often below the 10% chance of success.
|
/* Sample less often below the 10% chance of success.
|
||||||
* Sample less often above the 95% chance of success. */
|
* Sample less often above the 95% chance of success. */
|
||||||
if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
|
if (mrs->prob_avg > MINSTREL_FRAC(95, 100) ||
|
||||||
mrs->prob_ewma < MINSTREL_FRAC(10, 100)) {
|
mrs->prob_avg < MINSTREL_FRAC(10, 100)) {
|
||||||
mr->adjusted_retry_count = mrs->retry_count >> 1;
|
mr->adjusted_retry_count = mrs->retry_count >> 1;
|
||||||
if (mr->adjusted_retry_count > 2)
|
if (mr->adjusted_retry_count > 2)
|
||||||
mr->adjusted_retry_count = 2;
|
mr->adjusted_retry_count = 2;
|
||||||
|
@ -225,14 +229,14 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
|
||||||
* choose the maximum throughput rate as max_prob_rate
|
* choose the maximum throughput rate as max_prob_rate
|
||||||
* (2) if all success probabilities < 95%, the rate with
|
* (2) if all success probabilities < 95%, the rate with
|
||||||
* highest success probability is chosen as max_prob_rate */
|
* highest success probability is chosen as max_prob_rate */
|
||||||
if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) {
|
if (mrs->prob_avg >= MINSTREL_FRAC(95, 100)) {
|
||||||
tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_ewma);
|
tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_avg);
|
||||||
tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate],
|
tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate],
|
||||||
tmp_mrs->prob_ewma);
|
tmp_mrs->prob_avg);
|
||||||
if (tmp_cur_tp >= tmp_prob_tp)
|
if (tmp_cur_tp >= tmp_prob_tp)
|
||||||
tmp_prob_rate = i;
|
tmp_prob_rate = i;
|
||||||
} else {
|
} else {
|
||||||
if (mrs->prob_ewma >= tmp_mrs->prob_ewma)
|
if (mrs->prob_avg >= tmp_mrs->prob_avg)
|
||||||
tmp_prob_rate = i;
|
tmp_prob_rate = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,7 +294,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||||
mi->sample_deferred--;
|
mi->sample_deferred--;
|
||||||
|
|
||||||
if (time_after(jiffies, mi->last_stats_update +
|
if (time_after(jiffies, mi->last_stats_update +
|
||||||
(mp->update_interval * HZ) / 1000))
|
mp->update_interval / (mp->new_avg ? 2 : 1)))
|
||||||
minstrel_update_stats(mp, mi);
|
minstrel_update_stats(mp, mi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +426,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
|
||||||
* has a probability of >95%, we shouldn't be attempting
|
* has a probability of >95%, we shouldn't be attempting
|
||||||
* to use it, as this only wastes precious airtime */
|
* to use it, as this only wastes precious airtime */
|
||||||
if (!mrr_capable &&
|
if (!mrr_capable &&
|
||||||
(mi->r[ndx].stats.prob_ewma > MINSTREL_FRAC(95, 100)))
|
(mi->r[ndx].stats.prob_avg > MINSTREL_FRAC(95, 100)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mi->prev_sample = true;
|
mi->prev_sample = true;
|
||||||
|
@ -573,7 +577,7 @@ static u32 minstrel_get_expected_throughput(void *priv_sta)
|
||||||
* computing cur_tp
|
* computing cur_tp
|
||||||
*/
|
*/
|
||||||
tmp_mrs = &mi->r[idx].stats;
|
tmp_mrs = &mi->r[idx].stats;
|
||||||
tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10;
|
tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_avg) * 10;
|
||||||
tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
|
tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
|
||||||
|
|
||||||
return tmp_cur_tp;
|
return tmp_cur_tp;
|
||||||
|
|
|
@ -18,6 +18,21 @@
|
||||||
/* number of highest throughput rates to consider*/
|
/* number of highest throughput rates to consider*/
|
||||||
#define MAX_THR_RATES 4
|
#define MAX_THR_RATES 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coefficients for moving average with noise filter (period=16),
|
||||||
|
* scaled by 10 bits
|
||||||
|
*
|
||||||
|
* a1 = exp(-pi * sqrt(2) / period)
|
||||||
|
* coeff2 = 2 * a1 * cos(sqrt(2) * 2 * pi / period)
|
||||||
|
* coeff3 = -sqr(a1)
|
||||||
|
* coeff1 = 1 - coeff2 - coeff3
|
||||||
|
*/
|
||||||
|
#define MINSTREL_AVG_COEFF1 (MINSTREL_FRAC(1, 1) - \
|
||||||
|
MINSTREL_AVG_COEFF2 - \
|
||||||
|
MINSTREL_AVG_COEFF3)
|
||||||
|
#define MINSTREL_AVG_COEFF2 0x00001499
|
||||||
|
#define MINSTREL_AVG_COEFF3 -0x0000092e
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform EWMA (Exponentially Weighted Moving Average) calculation
|
* Perform EWMA (Exponentially Weighted Moving Average) calculation
|
||||||
*/
|
*/
|
||||||
|
@ -32,6 +47,37 @@ minstrel_ewma(int old, int new, int weight)
|
||||||
return old + incr;
|
return old + incr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in)
|
||||||
|
{
|
||||||
|
s32 out_1 = *prev_1;
|
||||||
|
s32 out_2 = *prev_2;
|
||||||
|
s32 val;
|
||||||
|
|
||||||
|
if (!in)
|
||||||
|
in += 1;
|
||||||
|
|
||||||
|
if (!out_1) {
|
||||||
|
val = out_1 = in;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = MINSTREL_AVG_COEFF1 * in;
|
||||||
|
val += MINSTREL_AVG_COEFF2 * out_1;
|
||||||
|
val += MINSTREL_AVG_COEFF3 * out_2;
|
||||||
|
val >>= MINSTREL_SCALE;
|
||||||
|
|
||||||
|
if (val > 1 << MINSTREL_SCALE)
|
||||||
|
val = 1 << MINSTREL_SCALE;
|
||||||
|
if (val < 0)
|
||||||
|
val = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
*prev_2 = out_1;
|
||||||
|
*prev_1 = val;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
struct minstrel_rate_stats {
|
struct minstrel_rate_stats {
|
||||||
/* current / last sampling period attempts/success counters */
|
/* current / last sampling period attempts/success counters */
|
||||||
u16 attempts, last_attempts;
|
u16 attempts, last_attempts;
|
||||||
|
@ -40,8 +86,9 @@ struct minstrel_rate_stats {
|
||||||
/* total attempts/success counters */
|
/* total attempts/success counters */
|
||||||
u32 att_hist, succ_hist;
|
u32 att_hist, succ_hist;
|
||||||
|
|
||||||
/* prob_ewma - exponential weighted moving average of prob */
|
/* prob_avg - moving average of prob */
|
||||||
u16 prob_ewma;
|
u16 prob_avg;
|
||||||
|
u16 prob_avg_1;
|
||||||
|
|
||||||
/* maximum retry counts */
|
/* maximum retry counts */
|
||||||
u8 retry_count;
|
u8 retry_count;
|
||||||
|
@ -95,6 +142,7 @@ struct minstrel_sta_info {
|
||||||
struct minstrel_priv {
|
struct minstrel_priv {
|
||||||
struct ieee80211_hw *hw;
|
struct ieee80211_hw *hw;
|
||||||
bool has_mrr;
|
bool has_mrr;
|
||||||
|
bool new_avg;
|
||||||
u32 sample_switch;
|
u32 sample_switch;
|
||||||
unsigned int cw_min;
|
unsigned int cw_min;
|
||||||
unsigned int cw_max;
|
unsigned int cw_max;
|
||||||
|
@ -126,8 +174,9 @@ extern const struct rate_control_ops mac80211_minstrel;
|
||||||
void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
|
void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
|
||||||
|
|
||||||
/* Recalculate success probabilities and counters for a given rate using EWMA */
|
/* Recalculate success probabilities and counters for a given rate using EWMA */
|
||||||
void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
|
void minstrel_calc_rate_stats(struct minstrel_priv *mp,
|
||||||
int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma);
|
struct minstrel_rate_stats *mrs);
|
||||||
|
int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg);
|
||||||
|
|
||||||
/* debugfs */
|
/* debugfs */
|
||||||
int minstrel_stats_open(struct inode *inode, struct file *file);
|
int minstrel_stats_open(struct inode *inode, struct file *file);
|
||||||
|
|
|
@ -90,8 +90,8 @@ minstrel_stats_open(struct inode *inode, struct file *file)
|
||||||
p += sprintf(p, "%6u ", mr->perfect_tx_time);
|
p += sprintf(p, "%6u ", mr->perfect_tx_time);
|
||||||
|
|
||||||
tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
|
tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
|
||||||
tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
|
tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg);
|
||||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
|
||||||
|
|
||||||
p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u"
|
p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u"
|
||||||
" %3u %3u %-3u "
|
" %3u %3u %-3u "
|
||||||
|
@ -147,8 +147,8 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
|
||||||
p += sprintf(p, "%u,",mr->perfect_tx_time);
|
p += sprintf(p, "%u,",mr->perfect_tx_time);
|
||||||
|
|
||||||
tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
|
tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
|
||||||
tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
|
tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg);
|
||||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
|
||||||
|
|
||||||
p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
|
p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
|
||||||
"%llu,%llu,%d,%d\n",
|
"%llu,%llu,%d,%d\n",
|
||||||
|
|
|
@ -346,12 +346,12 @@ minstrel_ht_avg_ampdu_len(struct minstrel_ht_sta *mi)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
|
minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
|
||||||
int prob_ewma)
|
int prob_avg)
|
||||||
{
|
{
|
||||||
unsigned int nsecs = 0;
|
unsigned int nsecs = 0;
|
||||||
|
|
||||||
/* do not account throughput if sucess prob is below 10% */
|
/* do not account throughput if sucess prob is below 10% */
|
||||||
if (prob_ewma < MINSTREL_FRAC(10, 100))
|
if (prob_avg < MINSTREL_FRAC(10, 100))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (group != MINSTREL_CCK_GROUP)
|
if (group != MINSTREL_CCK_GROUP)
|
||||||
|
@ -365,11 +365,11 @@ minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
|
||||||
* account for collision related packet error rate fluctuation
|
* account for collision related packet error rate fluctuation
|
||||||
* (prob is scaled - see MINSTREL_FRAC above)
|
* (prob is scaled - see MINSTREL_FRAC above)
|
||||||
*/
|
*/
|
||||||
if (prob_ewma > MINSTREL_FRAC(90, 100))
|
if (prob_avg > MINSTREL_FRAC(90, 100))
|
||||||
return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000)
|
return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000)
|
||||||
/ nsecs));
|
/ nsecs));
|
||||||
else
|
else
|
||||||
return MINSTREL_TRUNC(100000 * ((prob_ewma * 1000) / nsecs));
|
return MINSTREL_TRUNC(100000 * ((prob_avg * 1000) / nsecs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -389,13 +389,13 @@ minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index,
|
||||||
|
|
||||||
cur_group = index / MCS_GROUP_RATES;
|
cur_group = index / MCS_GROUP_RATES;
|
||||||
cur_idx = index % MCS_GROUP_RATES;
|
cur_idx = index % MCS_GROUP_RATES;
|
||||||
cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma;
|
cur_prob = mi->groups[cur_group].rates[cur_idx].prob_avg;
|
||||||
cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob);
|
cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
|
tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
|
||||||
tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
|
tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
|
||||||
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
|
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
|
||||||
tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx,
|
tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx,
|
||||||
tmp_prob);
|
tmp_prob);
|
||||||
if (cur_tp_avg < tmp_tp_avg ||
|
if (cur_tp_avg < tmp_tp_avg ||
|
||||||
|
@ -432,7 +432,7 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
|
||||||
|
|
||||||
tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
|
tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
|
||||||
tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
|
tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
|
||||||
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
|
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
|
||||||
tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
||||||
|
|
||||||
/* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
|
/* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
|
||||||
|
@ -444,11 +444,11 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
|
||||||
|
|
||||||
max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
|
max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
|
||||||
max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
|
max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
|
||||||
max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma;
|
max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
|
||||||
|
|
||||||
if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) {
|
if (mrs->prob_avg > MINSTREL_FRAC(75, 100)) {
|
||||||
cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx,
|
cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx,
|
||||||
mrs->prob_ewma);
|
mrs->prob_avg);
|
||||||
if (cur_tp_avg > tmp_tp_avg)
|
if (cur_tp_avg > tmp_tp_avg)
|
||||||
mi->max_prob_rate = index;
|
mi->max_prob_rate = index;
|
||||||
|
|
||||||
|
@ -458,9 +458,9 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
|
||||||
if (cur_tp_avg > max_gpr_tp_avg)
|
if (cur_tp_avg > max_gpr_tp_avg)
|
||||||
mg->max_group_prob_rate = index;
|
mg->max_group_prob_rate = index;
|
||||||
} else {
|
} else {
|
||||||
if (mrs->prob_ewma > tmp_prob)
|
if (mrs->prob_avg > tmp_prob)
|
||||||
mi->max_prob_rate = index;
|
mi->max_prob_rate = index;
|
||||||
if (mrs->prob_ewma > max_gpr_prob)
|
if (mrs->prob_avg > max_gpr_prob)
|
||||||
mg->max_group_prob_rate = index;
|
mg->max_group_prob_rate = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,12 +482,12 @@ minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
|
||||||
|
|
||||||
tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES;
|
tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES;
|
||||||
tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES;
|
tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES;
|
||||||
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
|
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
|
||||||
tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
||||||
|
|
||||||
tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES;
|
tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES;
|
||||||
tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES;
|
tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES;
|
||||||
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
|
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
|
||||||
tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
||||||
|
|
||||||
if (tmp_cck_tp_rate && tmp_cck_tp > tmp_mcs_tp) {
|
if (tmp_cck_tp_rate && tmp_cck_tp > tmp_mcs_tp) {
|
||||||
|
@ -518,7 +518,7 @@ minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
|
tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
|
||||||
tmp_prob = mi->groups[group].rates[tmp_idx].prob_ewma;
|
tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg;
|
||||||
|
|
||||||
if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) &&
|
if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) &&
|
||||||
(minstrel_mcs_groups[group].streams < tmp_max_streams)) {
|
(minstrel_mcs_groups[group].streams < tmp_max_streams)) {
|
||||||
|
@ -623,7 +623,7 @@ minstrel_ht_rate_sample_switch(struct minstrel_priv *mp,
|
||||||
* If that fails, look again for a rate that is at least as fast
|
* If that fails, look again for a rate that is at least as fast
|
||||||
*/
|
*/
|
||||||
mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
|
mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
|
||||||
faster_rate = mrs->prob_ewma > MINSTREL_FRAC(75, 100);
|
faster_rate = mrs->prob_avg > MINSTREL_FRAC(75, 100);
|
||||||
minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate);
|
minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate);
|
||||||
if (!n_rates && faster_rate)
|
if (!n_rates && faster_rate)
|
||||||
minstrel_ht_find_probe_rates(mi, rates, &n_rates, false);
|
minstrel_ht_find_probe_rates(mi, rates, &n_rates, false);
|
||||||
|
@ -737,8 +737,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
|
||||||
|
|
||||||
mrs = &mg->rates[i];
|
mrs = &mg->rates[i];
|
||||||
mrs->retry_updated = false;
|
mrs->retry_updated = false;
|
||||||
minstrel_calc_rate_stats(mrs);
|
minstrel_calc_rate_stats(mp, mrs);
|
||||||
cur_prob = mrs->prob_ewma;
|
cur_prob = mrs->prob_avg;
|
||||||
|
|
||||||
if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0)
|
if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -773,6 +773,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
|
||||||
|
|
||||||
/* try to sample all available rates during each interval */
|
/* try to sample all available rates during each interval */
|
||||||
mi->sample_count *= 8;
|
mi->sample_count *= 8;
|
||||||
|
if (mp->new_avg)
|
||||||
|
mi->sample_count /= 2;
|
||||||
|
|
||||||
if (sample)
|
if (sample)
|
||||||
minstrel_ht_rate_sample_switch(mp, mi);
|
minstrel_ht_rate_sample_switch(mp, mi);
|
||||||
|
@ -889,6 +891,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||||
struct ieee80211_tx_rate *ar = info->status.rates;
|
struct ieee80211_tx_rate *ar = info->status.rates;
|
||||||
struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL;
|
struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL;
|
||||||
struct minstrel_priv *mp = priv;
|
struct minstrel_priv *mp = priv;
|
||||||
|
u32 update_interval = mp->update_interval / 2;
|
||||||
bool last, update = false;
|
bool last, update = false;
|
||||||
bool sample_status = false;
|
bool sample_status = false;
|
||||||
int i;
|
int i;
|
||||||
|
@ -943,6 +946,10 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||||
|
|
||||||
switch (mi->sample_mode) {
|
switch (mi->sample_mode) {
|
||||||
case MINSTREL_SAMPLE_IDLE:
|
case MINSTREL_SAMPLE_IDLE:
|
||||||
|
if (mp->new_avg &&
|
||||||
|
(mp->hw->max_rates > 1 ||
|
||||||
|
mi->total_packets_cur < SAMPLE_SWITCH_THR))
|
||||||
|
update_interval /= 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINSTREL_SAMPLE_ACTIVE:
|
case MINSTREL_SAMPLE_ACTIVE:
|
||||||
|
@ -970,23 +977,20 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||||
*/
|
*/
|
||||||
rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
|
rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
|
||||||
if (rate->attempts > 30 &&
|
if (rate->attempts > 30 &&
|
||||||
MINSTREL_FRAC(rate->success, rate->attempts) <
|
rate->success < rate->attempts / 4) {
|
||||||
MINSTREL_FRAC(20, 100)) {
|
|
||||||
minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true);
|
minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true);
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]);
|
rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]);
|
||||||
if (rate2->attempts > 30 &&
|
if (rate2->attempts > 30 &&
|
||||||
MINSTREL_FRAC(rate2->success, rate2->attempts) <
|
rate2->success < rate2->attempts / 4) {
|
||||||
MINSTREL_FRAC(20, 100)) {
|
|
||||||
minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false);
|
minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false);
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (time_after(jiffies, mi->last_stats_update +
|
if (time_after(jiffies, mi->last_stats_update + update_interval)) {
|
||||||
(mp->update_interval / 2 * HZ) / 1000)) {
|
|
||||||
update = true;
|
update = true;
|
||||||
minstrel_ht_update_stats(mp, mi, true);
|
minstrel_ht_update_stats(mp, mi, true);
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +1012,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
|
||||||
unsigned int overhead = 0, overhead_rtscts = 0;
|
unsigned int overhead = 0, overhead_rtscts = 0;
|
||||||
|
|
||||||
mrs = minstrel_get_ratestats(mi, index);
|
mrs = minstrel_get_ratestats(mi, index);
|
||||||
if (mrs->prob_ewma < MINSTREL_FRAC(1, 10)) {
|
if (mrs->prob_avg < MINSTREL_FRAC(1, 10)) {
|
||||||
mrs->retry_count = 1;
|
mrs->retry_count = 1;
|
||||||
mrs->retry_count_rtscts = 1;
|
mrs->retry_count_rtscts = 1;
|
||||||
return;
|
return;
|
||||||
|
@ -1065,7 +1069,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
|
||||||
if (!mrs->retry_updated)
|
if (!mrs->retry_updated)
|
||||||
minstrel_calc_retransmit(mp, mi, index);
|
minstrel_calc_retransmit(mp, mi, index);
|
||||||
|
|
||||||
if (mrs->prob_ewma < MINSTREL_FRAC(20, 100) || !mrs->retry_count) {
|
if (mrs->prob_avg < MINSTREL_FRAC(20, 100) || !mrs->retry_count) {
|
||||||
ratetbl->rate[offset].count = 2;
|
ratetbl->rate[offset].count = 2;
|
||||||
ratetbl->rate[offset].count_rts = 2;
|
ratetbl->rate[offset].count_rts = 2;
|
||||||
ratetbl->rate[offset].count_cts = 2;
|
ratetbl->rate[offset].count_cts = 2;
|
||||||
|
@ -1099,11 +1103,11 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
minstrel_ht_get_prob_ewma(struct minstrel_ht_sta *mi, int rate)
|
minstrel_ht_get_prob_avg(struct minstrel_ht_sta *mi, int rate)
|
||||||
{
|
{
|
||||||
int group = rate / MCS_GROUP_RATES;
|
int group = rate / MCS_GROUP_RATES;
|
||||||
rate %= MCS_GROUP_RATES;
|
rate %= MCS_GROUP_RATES;
|
||||||
return mi->groups[group].rates[rate].prob_ewma;
|
return mi->groups[group].rates[rate].prob_avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1115,7 +1119,7 @@ minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi)
|
||||||
unsigned int duration;
|
unsigned int duration;
|
||||||
|
|
||||||
/* Disable A-MSDU if max_prob_rate is bad */
|
/* Disable A-MSDU if max_prob_rate is bad */
|
||||||
if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
|
if (mi->groups[group].rates[rate].prob_avg < MINSTREL_FRAC(50, 100))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
duration = g->duration[rate];
|
duration = g->duration[rate];
|
||||||
|
@ -1138,7 +1142,7 @@ minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi)
|
||||||
* data packet size
|
* data packet size
|
||||||
*/
|
*/
|
||||||
if (duration > MCS_DURATION(1, 0, 260) ||
|
if (duration > MCS_DURATION(1, 0, 260) ||
|
||||||
(minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
|
(minstrel_ht_get_prob_avg(mi, mi->max_tp_rate[0]) <
|
||||||
MINSTREL_FRAC(75, 100)))
|
MINSTREL_FRAC(75, 100)))
|
||||||
return 3200;
|
return 3200;
|
||||||
|
|
||||||
|
@ -1243,7 +1247,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
|
||||||
* rate, to avoid wasting airtime.
|
* rate, to avoid wasting airtime.
|
||||||
*/
|
*/
|
||||||
sample_dur = minstrel_get_duration(sample_idx);
|
sample_dur = minstrel_get_duration(sample_idx);
|
||||||
if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
|
if (mrs->prob_avg > MINSTREL_FRAC(95, 100) ||
|
||||||
minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur)
|
minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -1666,7 +1670,8 @@ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
|
||||||
mp->has_mrr = true;
|
mp->has_mrr = true;
|
||||||
|
|
||||||
mp->hw = hw;
|
mp->hw = hw;
|
||||||
mp->update_interval = 100;
|
mp->update_interval = HZ / 10;
|
||||||
|
mp->new_avg = true;
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||||
mp->fixed_rate_idx = (u32) -1;
|
mp->fixed_rate_idx = (u32) -1;
|
||||||
|
@ -1674,6 +1679,8 @@ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
|
||||||
&mp->fixed_rate_idx);
|
&mp->fixed_rate_idx);
|
||||||
debugfs_create_u32("sample_switch", S_IRUGO | S_IWUSR, debugfsdir,
|
debugfs_create_u32("sample_switch", S_IRUGO | S_IWUSR, debugfsdir,
|
||||||
&mp->sample_switch);
|
&mp->sample_switch);
|
||||||
|
debugfs_create_bool("new_avg", S_IRUGO | S_IWUSR, debugfsdir,
|
||||||
|
&mp->new_avg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
minstrel_ht_init_cck_rates(mp);
|
minstrel_ht_init_cck_rates(mp);
|
||||||
|
@ -1698,7 +1705,7 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
|
||||||
|
|
||||||
i = mi->max_tp_rate[0] / MCS_GROUP_RATES;
|
i = mi->max_tp_rate[0] / MCS_GROUP_RATES;
|
||||||
j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
|
j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
|
||||||
prob = mi->groups[i].rates[j].prob_ewma;
|
prob = mi->groups[i].rates[j].prob_avg;
|
||||||
|
|
||||||
/* convert tp_avg from pkt per second in kbps */
|
/* convert tp_avg from pkt per second in kbps */
|
||||||
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10;
|
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10;
|
||||||
|
|
|
@ -119,6 +119,6 @@ struct minstrel_ht_sta_priv {
|
||||||
|
|
||||||
void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
|
void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
|
||||||
int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
|
int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
|
||||||
int prob_ewma);
|
int prob_avg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -98,8 +98,8 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
|
||||||
p += sprintf(p, "%6u ", tx_time);
|
p += sprintf(p, "%6u ", tx_time);
|
||||||
|
|
||||||
tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
|
tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
|
||||||
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
|
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg);
|
||||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
|
||||||
|
|
||||||
p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u"
|
p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u"
|
||||||
" %3u %3u %-3u "
|
" %3u %3u %-3u "
|
||||||
|
@ -243,8 +243,8 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
|
||||||
p += sprintf(p, "%u,", tx_time);
|
p += sprintf(p, "%u,", tx_time);
|
||||||
|
|
||||||
tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
|
tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
|
||||||
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
|
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg);
|
||||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
|
||||||
|
|
||||||
p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,"
|
p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,"
|
||||||
"%u,%llu,%llu,",
|
"%u,%llu,%llu,",
|
||||||
|
|
|
@ -1617,7 +1617,7 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
|
||||||
|
|
||||||
static bool ieee80211_tx_frags(struct ieee80211_local *local,
|
static bool ieee80211_tx_frags(struct ieee80211_local *local,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct sta_info *sta,
|
||||||
struct sk_buff_head *skbs,
|
struct sk_buff_head *skbs,
|
||||||
bool txpending)
|
bool txpending)
|
||||||
{
|
{
|
||||||
|
@ -1679,7 +1679,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
|
||||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||||
|
|
||||||
info->control.vif = vif;
|
info->control.vif = vif;
|
||||||
control.sta = sta;
|
control.sta = sta ? &sta->sta : NULL;
|
||||||
|
|
||||||
__skb_unlink(skb, skbs);
|
__skb_unlink(skb, skbs);
|
||||||
drv_tx(local, &control, skb);
|
drv_tx(local, &control, skb);
|
||||||
|
@ -1698,7 +1698,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
struct ieee80211_vif *vif;
|
struct ieee80211_vif *vif;
|
||||||
struct ieee80211_sta *pubsta;
|
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
bool result = true;
|
bool result = true;
|
||||||
__le16 fc;
|
__le16 fc;
|
||||||
|
@ -1713,11 +1712,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
|
||||||
if (sta && !sta->uploaded)
|
if (sta && !sta->uploaded)
|
||||||
sta = NULL;
|
sta = NULL;
|
||||||
|
|
||||||
if (sta)
|
|
||||||
pubsta = &sta->sta;
|
|
||||||
else
|
|
||||||
pubsta = NULL;
|
|
||||||
|
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_MONITOR:
|
case NL80211_IFTYPE_MONITOR:
|
||||||
if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
|
if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
|
||||||
|
@ -1744,8 +1738,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ieee80211_tx_frags(local, vif, pubsta, skbs,
|
result = ieee80211_tx_frags(local, vif, sta, skbs, txpending);
|
||||||
txpending);
|
|
||||||
|
|
||||||
ieee80211_tpt_led_trig_tx(local, fc, led_len);
|
ieee80211_tpt_led_trig_tx(local, fc, led_len);
|
||||||
|
|
||||||
|
@ -3529,7 +3522,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_sub_if_data, u.ap);
|
struct ieee80211_sub_if_data, u.ap);
|
||||||
|
|
||||||
__skb_queue_tail(&tx.skbs, skb);
|
__skb_queue_tail(&tx.skbs, skb);
|
||||||
ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
|
ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8265,10 +8265,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||||
/* leave request id zero for legacy request
|
/* leave request id zero for legacy request
|
||||||
* or if driver does not support multi-scheduled scan
|
* or if driver does not support multi-scheduled scan
|
||||||
*/
|
*/
|
||||||
if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1) {
|
if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
|
||||||
while (!sched_scan_req->reqid)
|
sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
|
||||||
sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
|
err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
Loading…
Reference in a new issue