diff options
author | Eyal Shapira <eyal@wizery.com> | 2014-09-14 08:23:23 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-09-21 06:25:45 -0400 |
commit | 1ebc8f2ef83d182941e741af4b59dc904f12853c (patch) | |
tree | 0de970aeb5d14df952221aacffa2e26251b3edc6 | |
parent | 361dbec8acffe0201486f1750353a26d21cfff32 (diff) |
iwlwifi: mvm: rs: refactor to allow direct rs updating
Enable RS to get updated directly via iwl_mvm_rs_tx_status
which will be called by the driver and not via mac80211
rate control. This is required for a following patch to
report on BAs which do not cause the BA window to progress.
Also this is a first step in decoupling rs from the
mac80211 rate control.
Signed-off-by: Eyal Shapira <eyalx.shapira@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rs.c | 98 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rs.h | 4 |
2 files changed, 52 insertions, 50 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index d179a8eb50df..1865ba68b6e5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -377,9 +377,9 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
377 | } | 377 | } |
378 | 378 | ||
379 | static void rs_rate_scale_perform(struct iwl_mvm *mvm, | 379 | static void rs_rate_scale_perform(struct iwl_mvm *mvm, |
380 | struct sk_buff *skb, | 380 | struct ieee80211_sta *sta, |
381 | struct ieee80211_sta *sta, | 381 | struct iwl_lq_sta *lq_sta, |
382 | struct iwl_lq_sta *lq_sta); | 382 | int tid); |
383 | static void rs_fill_lq_cmd(struct iwl_mvm *mvm, | 383 | static void rs_fill_lq_cmd(struct iwl_mvm *mvm, |
384 | struct ieee80211_sta *sta, | 384 | struct ieee80211_sta *sta, |
385 | struct iwl_lq_sta *lq_sta, | 385 | struct iwl_lq_sta *lq_sta, |
@@ -1007,27 +1007,35 @@ static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) | |||
1007 | return RATE_MCS_CHAN_WIDTH_20; | 1007 | return RATE_MCS_CHAN_WIDTH_20; |
1008 | } | 1008 | } |
1009 | 1009 | ||
1010 | /* | 1010 | static u8 rs_get_tid(struct ieee80211_hdr *hdr) |
1011 | * mac80211 sends us Tx status | 1011 | { |
1012 | */ | 1012 | u8 tid = IWL_MAX_TID_COUNT; |
1013 | static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | 1013 | |
1014 | struct ieee80211_sta *sta, void *priv_sta, | 1014 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
1015 | struct sk_buff *skb) | 1015 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
1016 | tid = qc[0] & 0xf; | ||
1017 | } | ||
1018 | |||
1019 | if (unlikely(tid > IWL_MAX_TID_COUNT)) | ||
1020 | tid = IWL_MAX_TID_COUNT; | ||
1021 | |||
1022 | return tid; | ||
1023 | } | ||
1024 | |||
1025 | void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | ||
1026 | int tid, struct ieee80211_tx_info *info) | ||
1016 | { | 1027 | { |
1017 | int legacy_success; | 1028 | int legacy_success; |
1018 | int retries; | 1029 | int retries; |
1019 | int mac_index, i; | 1030 | int mac_index, i; |
1020 | struct iwl_lq_sta *lq_sta = priv_sta; | ||
1021 | struct iwl_lq_cmd *table; | 1031 | struct iwl_lq_cmd *table; |
1022 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1023 | struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_r; | ||
1024 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
1025 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1026 | enum mac80211_rate_control_flags mac_flags; | 1032 | enum mac80211_rate_control_flags mac_flags; |
1027 | u32 ucode_rate; | 1033 | u32 ucode_rate; |
1028 | struct rs_rate rate; | 1034 | struct rs_rate rate; |
1029 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; | 1035 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
1030 | u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0]; | 1036 | u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0]; |
1037 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
1038 | struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta; | ||
1031 | 1039 | ||
1032 | /* Treat uninitialized rate scaling data same as non-existing. */ | 1040 | /* Treat uninitialized rate scaling data same as non-existing. */ |
1033 | if (!lq_sta) { | 1041 | if (!lq_sta) { |
@@ -1045,10 +1053,6 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
1045 | return; | 1053 | return; |
1046 | } | 1054 | } |
1047 | #endif | 1055 | #endif |
1048 | if (!ieee80211_is_data(hdr->frame_control) || | ||
1049 | info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
1050 | return; | ||
1051 | |||
1052 | /* This packet was aggregated but doesn't carry status info */ | 1056 | /* This packet was aggregated but doesn't carry status info */ |
1053 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 1057 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
1054 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 1058 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
@@ -1094,7 +1098,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
1094 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) | 1098 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) |
1095 | ieee80211_stop_tx_ba_session(sta, tid); | 1099 | ieee80211_stop_tx_ba_session(sta, tid); |
1096 | 1100 | ||
1097 | iwl_mvm_rs_rate_init(mvm, sta, sband->band, false); | 1101 | iwl_mvm_rs_rate_init(mvm, sta, info->band, false); |
1098 | return; | 1102 | return; |
1099 | } | 1103 | } |
1100 | lq_sta->last_tx = jiffies; | 1104 | lq_sta->last_tx = jiffies; |
@@ -1221,8 +1225,28 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
1221 | IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); | 1225 | IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); |
1222 | done: | 1226 | done: |
1223 | /* See if there's a better rate or modulation mode to try. */ | 1227 | /* See if there's a better rate or modulation mode to try. */ |
1224 | if (sta && sta->supp_rates[sband->band]) | 1228 | if (sta && sta->supp_rates[info->band]) |
1225 | rs_rate_scale_perform(mvm, skb, sta, lq_sta); | 1229 | rs_rate_scale_perform(mvm, sta, lq_sta, tid); |
1230 | } | ||
1231 | |||
1232 | /* | ||
1233 | * mac80211 sends us Tx status | ||
1234 | */ | ||
1235 | static void rs_mac80211_tx_status(void *mvm_r, | ||
1236 | struct ieee80211_supported_band *sband, | ||
1237 | struct ieee80211_sta *sta, void *priv_sta, | ||
1238 | struct sk_buff *skb) | ||
1239 | { | ||
1240 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1241 | struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_r; | ||
1242 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
1243 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1244 | |||
1245 | if (!ieee80211_is_data(hdr->frame_control) || | ||
1246 | info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
1247 | return; | ||
1248 | |||
1249 | iwl_mvm_rs_tx_status(mvm, sta, rs_get_tid(hdr), info); | ||
1226 | } | 1250 | } |
1227 | 1251 | ||
1228 | /* | 1252 | /* |
@@ -1493,22 +1517,6 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm, | |||
1493 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); | 1517 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); |
1494 | } | 1518 | } |
1495 | 1519 | ||
1496 | static u8 rs_get_tid(struct iwl_lq_sta *lq_data, | ||
1497 | struct ieee80211_hdr *hdr) | ||
1498 | { | ||
1499 | u8 tid = IWL_MAX_TID_COUNT; | ||
1500 | |||
1501 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
1502 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
1503 | tid = qc[0] & 0xf; | ||
1504 | } | ||
1505 | |||
1506 | if (unlikely(tid > IWL_MAX_TID_COUNT)) | ||
1507 | tid = IWL_MAX_TID_COUNT; | ||
1508 | |||
1509 | return tid; | ||
1510 | } | ||
1511 | |||
1512 | static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, | 1520 | static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, |
1513 | struct iwl_lq_sta *lq_sta, | 1521 | struct iwl_lq_sta *lq_sta, |
1514 | struct ieee80211_sta *sta, | 1522 | struct ieee80211_sta *sta, |
@@ -1947,12 +1955,10 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm, | |||
1947 | * Do rate scaling and search for new modulation mode. | 1955 | * Do rate scaling and search for new modulation mode. |
1948 | */ | 1956 | */ |
1949 | static void rs_rate_scale_perform(struct iwl_mvm *mvm, | 1957 | static void rs_rate_scale_perform(struct iwl_mvm *mvm, |
1950 | struct sk_buff *skb, | ||
1951 | struct ieee80211_sta *sta, | 1958 | struct ieee80211_sta *sta, |
1952 | struct iwl_lq_sta *lq_sta) | 1959 | struct iwl_lq_sta *lq_sta, |
1960 | int tid) | ||
1953 | { | 1961 | { |
1954 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1955 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1956 | int low = IWL_RATE_INVALID; | 1962 | int low = IWL_RATE_INVALID; |
1957 | int high = IWL_RATE_INVALID; | 1963 | int high = IWL_RATE_INVALID; |
1958 | int index; | 1964 | int index; |
@@ -1969,19 +1975,11 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1969 | u8 done_search = 0; | 1975 | u8 done_search = 0; |
1970 | u16 high_low; | 1976 | u16 high_low; |
1971 | s32 sr; | 1977 | s32 sr; |
1972 | u8 tid = IWL_MAX_TID_COUNT; | ||
1973 | u8 prev_agg = lq_sta->is_agg; | 1978 | u8 prev_agg = lq_sta->is_agg; |
1974 | struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv; | 1979 | struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv; |
1975 | struct iwl_mvm_tid_data *tid_data; | 1980 | struct iwl_mvm_tid_data *tid_data; |
1976 | struct rs_rate *rate; | 1981 | struct rs_rate *rate; |
1977 | 1982 | ||
1978 | /* Send management frames and NO_ACK data using lowest rate. */ | ||
1979 | /* TODO: this could probably be improved.. */ | ||
1980 | if (!ieee80211_is_data(hdr->frame_control) || | ||
1981 | info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
1982 | return; | ||
1983 | |||
1984 | tid = rs_get_tid(lq_sta, hdr); | ||
1985 | if ((tid != IWL_MAX_TID_COUNT) && | 1983 | if ((tid != IWL_MAX_TID_COUNT) && |
1986 | (lq_sta->tx_agg_tid_en & (1 << tid))) { | 1984 | (lq_sta->tx_agg_tid_en & (1 << tid))) { |
1987 | tid_data = &sta_priv->tid_data[tid]; | 1985 | tid_data = &sta_priv->tid_data[tid]; |
@@ -3323,7 +3321,7 @@ static void rs_rate_init_stub(void *mvm_r, | |||
3323 | 3321 | ||
3324 | static const struct rate_control_ops rs_mvm_ops = { | 3322 | static const struct rate_control_ops rs_mvm_ops = { |
3325 | .name = RS_NAME, | 3323 | .name = RS_NAME, |
3326 | .tx_status = rs_tx_status, | 3324 | .tx_status = rs_mac80211_tx_status, |
3327 | .get_rate = rs_get_rate, | 3325 | .get_rate = rs_get_rate, |
3328 | .rate_init = rs_rate_init_stub, | 3326 | .rate_init = rs_rate_init_stub, |
3329 | .alloc = rs_alloc, | 3327 | .alloc = rs_alloc, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 95c4b960fd71..eb34c1209acc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
@@ -376,6 +376,10 @@ struct iwl_lq_sta { | |||
376 | void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | 376 | void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
377 | enum ieee80211_band band, bool init); | 377 | enum ieee80211_band band, bool init); |
378 | 378 | ||
379 | /* Notify RS about Tx status */ | ||
380 | void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | ||
381 | int tid, struct ieee80211_tx_info *info); | ||
382 | |||
379 | /** | 383 | /** |
380 | * iwl_rate_control_register - Register the rate control algorithm callbacks | 384 | * iwl_rate_control_register - Register the rate control algorithm callbacks |
381 | * | 385 | * |