diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/rs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rs.c | 80 |
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) | |||
505 | static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, | 505 | static 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 | ||
514 | static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) | 515 | static 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, | |||
992 | static inline bool rs_rate_match(struct rs_rate *a, | 1001 | static 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 | ||
998 | static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) | 1015 | static 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); |
1226 | done: | 1243 | done: |
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 | ||
1779 | static 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 | |||
1757 | static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, | 1802 | static 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 | */ |
2822 | static void rs_build_rates_table(struct iwl_mvm *mvm, | 2880 | static 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; |