aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/rs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/rs.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c80
1 files changed, 70 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 18a539999580..ce884847cc8a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -505,10 +505,11 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type)
505static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, 505static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
506 const char *prefix) 506 const char *prefix)
507{ 507{
508 IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d\n", 508 IWL_DEBUG_RATE(mvm,
509 "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC %d\n",
509 prefix, rs_pretty_lq_type(rate->type), 510 prefix, rs_pretty_lq_type(rate->type),
510 rate->index, rs_pretty_ant(rate->ant), 511 rate->index, rs_pretty_ant(rate->ant),
511 rate->bw, rate->sgi, rate->ldpc); 512 rate->bw, rate->sgi, rate->ldpc, rate->stbc);
512} 513}
513 514
514static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) 515static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
@@ -741,6 +742,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
741 IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type); 742 IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type);
742 } 743 }
743 744
745 if (is_siso(rate) && rate->stbc) {
746 /* To enable STBC we need to set both a flag and ANT_AB */
747 ucode_rate |= RATE_MCS_ANT_AB_MSK;
748 ucode_rate |= RATE_MCS_VHT_STBC_MSK;
749 }
750
744 ucode_rate |= rate->bw; 751 ucode_rate |= rate->bw;
745 if (rate->sgi) 752 if (rate->sgi)
746 ucode_rate |= RATE_MCS_SGI_MSK; 753 ucode_rate |= RATE_MCS_SGI_MSK;
@@ -785,6 +792,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
785 rate->sgi = true; 792 rate->sgi = true;
786 if (ucode_rate & RATE_MCS_LDPC_MSK) 793 if (ucode_rate & RATE_MCS_LDPC_MSK)
787 rate->ldpc = true; 794 rate->ldpc = true;
795 if (ucode_rate & RATE_MCS_VHT_STBC_MSK)
796 rate->stbc = true;
788 797
789 rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; 798 rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
790 799
@@ -794,7 +803,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
794 803
795 if (nss == 1) { 804 if (nss == 1) {
796 rate->type = LQ_HT_SISO; 805 rate->type = LQ_HT_SISO;
797 WARN_ON_ONCE(num_of_ant != 1); 806 WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
798 } else if (nss == 2) { 807 } else if (nss == 2) {
799 rate->type = LQ_HT_MIMO2; 808 rate->type = LQ_HT_MIMO2;
800 WARN_ON_ONCE(num_of_ant != 2); 809 WARN_ON_ONCE(num_of_ant != 2);
@@ -992,7 +1001,15 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
992static inline bool rs_rate_match(struct rs_rate *a, 1001static inline bool rs_rate_match(struct rs_rate *a,
993 struct rs_rate *b) 1002 struct rs_rate *b)
994{ 1003{
995 return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi); 1004 bool ant_match;
1005
1006 if (a->stbc)
1007 ant_match = (b->ant == ANT_A || b->ant == ANT_B);
1008 else
1009 ant_match = (a->ant == b->ant);
1010
1011 return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi)
1012 && ant_match;
996} 1013}
997 1014
998static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) 1015static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
@@ -1225,7 +1242,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1225 IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); 1242 IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
1226done: 1243done:
1227 /* See if there's a better rate or modulation mode to try. */ 1244 /* See if there's a better rate or modulation mode to try. */
1228 if (sta && sta->supp_rates[info->band]) 1245 if (sta->supp_rates[info->band])
1229 rs_rate_scale_perform(mvm, sta, lq_sta, tid); 1246 rs_rate_scale_perform(mvm, sta, lq_sta, tid);
1230} 1247}
1231 1248
@@ -1623,6 +1640,8 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
1623 else 1640 else
1624 rate->type = LQ_LEGACY_G; 1641 rate->type = LQ_LEGACY_G;
1625 1642
1643 rate->bw = RATE_MCS_CHAN_WIDTH_20;
1644 rate->ldpc = false;
1626 rate_mask = lq_sta->active_legacy_rate; 1645 rate_mask = lq_sta->active_legacy_rate;
1627 } else if (column->mode == RS_SISO) { 1646 } else if (column->mode == RS_SISO) {
1628 rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; 1647 rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;
@@ -1634,8 +1653,11 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
1634 WARN_ON_ONCE("Bad column mode"); 1653 WARN_ON_ONCE("Bad column mode");
1635 } 1654 }
1636 1655
1637 rate->bw = rs_bw_from_sta_bw(sta); 1656 if (column->mode != RS_LEGACY) {
1638 rate->ldpc = lq_sta->ldpc; 1657 rate->bw = rs_bw_from_sta_bw(sta);
1658 rate->ldpc = lq_sta->ldpc;
1659 }
1660
1639 search_tbl->column = col_id; 1661 search_tbl->column = col_id;
1640 rs_set_expected_tpt_table(lq_sta, search_tbl); 1662 rs_set_expected_tpt_table(lq_sta, search_tbl);
1641 1663
@@ -1754,6 +1776,29 @@ out:
1754 return action; 1776 return action;
1755} 1777}
1756 1778
1779static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1780 struct iwl_lq_sta *lq_sta)
1781{
1782 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1783 struct ieee80211_vif *vif = mvmsta->vif;
1784 bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
1785 !vif->bss_conf.ps);
1786
1787 /* Our chip supports Tx STBC and the peer is an HT/VHT STA which
1788 * supports STBC of at least 1*SS
1789 */
1790 if (!lq_sta->stbc)
1791 return false;
1792
1793 if (!mvm->ps_disabled && !sta_ps_disabled)
1794 return false;
1795
1796 if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
1797 return false;
1798
1799 return true;
1800}
1801
1757static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, 1802static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
1758 int *weaker, int *stronger) 1803 int *weaker, int *stronger)
1759{ 1804{
@@ -2675,6 +2720,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
2675 if (mvm->cfg->ht_params->ldpc && 2720 if (mvm->cfg->ht_params->ldpc &&
2676 (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) 2721 (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING))
2677 lq_sta->ldpc = true; 2722 lq_sta->ldpc = true;
2723
2724 if (mvm->cfg->ht_params->stbc &&
2725 (num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
2726 (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC))
2727 lq_sta->stbc = true;
2678 } else { 2728 } else {
2679 rs_vht_set_enabled_rates(sta, vht_cap, lq_sta); 2729 rs_vht_set_enabled_rates(sta, vht_cap, lq_sta);
2680 lq_sta->is_vht = true; 2730 lq_sta->is_vht = true;
@@ -2682,8 +2732,16 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
2682 if (mvm->cfg->ht_params->ldpc && 2732 if (mvm->cfg->ht_params->ldpc &&
2683 (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)) 2733 (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))
2684 lq_sta->ldpc = true; 2734 lq_sta->ldpc = true;
2735
2736 if (mvm->cfg->ht_params->stbc &&
2737 (num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
2738 (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))
2739 lq_sta->stbc = true;
2685 } 2740 }
2686 2741
2742 if (IWL_MVM_RS_DISABLE_MIMO)
2743 lq_sta->active_mimo2_rate = 0;
2744
2687 lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, 2745 lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
2688 BITS_PER_LONG); 2746 BITS_PER_LONG);
2689 lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, 2747 lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate,
@@ -2692,11 +2750,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
2692 BITS_PER_LONG); 2750 BITS_PER_LONG);
2693 2751
2694 IWL_DEBUG_RATE(mvm, 2752 IWL_DEBUG_RATE(mvm,
2695 "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d\n", 2753 "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC%d\n",
2696 lq_sta->active_legacy_rate, 2754 lq_sta->active_legacy_rate,
2697 lq_sta->active_siso_rate, 2755 lq_sta->active_siso_rate,
2698 lq_sta->active_mimo2_rate, 2756 lq_sta->active_mimo2_rate,
2699 lq_sta->is_vht, lq_sta->ldpc); 2757 lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc);
2700 IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", 2758 IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
2701 lq_sta->max_legacy_rate_idx, 2759 lq_sta->max_legacy_rate_idx,
2702 lq_sta->max_siso_rate_idx, 2760 lq_sta->max_siso_rate_idx,
@@ -2820,6 +2878,7 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm,
2820 * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps 2878 * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps
2821 */ 2879 */
2822static void rs_build_rates_table(struct iwl_mvm *mvm, 2880static void rs_build_rates_table(struct iwl_mvm *mvm,
2881 struct ieee80211_sta *sta,
2823 struct iwl_lq_sta *lq_sta, 2882 struct iwl_lq_sta *lq_sta,
2824 const struct rs_rate *initial_rate) 2883 const struct rs_rate *initial_rate)
2825{ 2884{
@@ -2832,6 +2891,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
2832 memcpy(&rate, initial_rate, sizeof(rate)); 2891 memcpy(&rate, initial_rate, sizeof(rate));
2833 2892
2834 valid_tx_ant = mvm->fw->valid_tx_ant; 2893 valid_tx_ant = mvm->fw->valid_tx_ant;
2894 rate.stbc = rs_stbc_allow(mvm, sta, lq_sta);
2835 2895
2836 if (is_siso(&rate)) { 2896 if (is_siso(&rate)) {
2837 num_rates = RS_INITIAL_SISO_NUM_RATES; 2897 num_rates = RS_INITIAL_SISO_NUM_RATES;
@@ -2903,7 +2963,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
2903 if (WARN_ON_ONCE(!sta || !initial_rate)) 2963 if (WARN_ON_ONCE(!sta || !initial_rate))
2904 return; 2964 return;
2905 2965
2906 rs_build_rates_table(mvm, lq_sta, initial_rate); 2966 rs_build_rates_table(mvm, sta, lq_sta, initial_rate);
2907 2967
2908 if (num_of_ant(initial_rate->ant) == 1) 2968 if (num_of_ant(initial_rate->ant) == 1)
2909 lq_cmd->single_stream_ant_msk = initial_rate->ant; 2969 lq_cmd->single_stream_ant_msk = initial_rate->ant;