2
0

972-ath10k_fix-crash-due-to-wrong-handling-of-peer_bw_rxnss_override-parameter.patch 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. From: Sebastian Gottschall <[email protected]>
  2. current handling of peer_bw_rxnss_override parameter is based on guessing the VHT160/8080 capability by rx rate. this is wrong and may lead
  3. to a non initialized peer_bw_rxnss_override parameter which is required since VHT160 operation mode only supports 2x2 chainmasks in addition the original code
  4. initialized the parameter with wrong masked values.
  5. This patch uses the peer phymode and peer nss information for correct initialisation of the peer_bw_rxnss_override parameter.
  6. if this peer information is not available, we initialize the parameter by minimum nss which is suggested by QCA as temporary workaround according
  7. to the QCA sourcecodes.
  8. Signed-off-by: Sebastian Gottschall <[email protected]>
  9. v2: remove debug messages
  10. v3: apply some cosmetics, update documentation
  11. v4: fix compile warning and truncate nss to maximum of 2x2 since current chipsets only support 2x2 at vht160
  12. v5: handle maximum nss for chipsets supportig vht160 with 1x1 only
  13. v7: use more simple code variant and take care about hw/sw chainmask configuration
  14. v8: fix some code style issues
  15. v9: use SM/MS macros from code.h to simplify shift/mask handling
  16. ---
  17. drivers/net/wireless/ath/ath10k/mac.c | 54 +++++++++++++++++++--------
  18. drivers/net/wireless/ath/ath10k/wmi.c | 7 +---
  19. drivers/net/wireless/ath/ath10k/wmi.h | 14 ++++++-
  20. 3 files changed, 52 insertions(+), 23 deletions(-)
  21. --- a/drivers/net/wireless/ath/ath10k/mac.c
  22. +++ b/drivers/net/wireless/ath/ath10k/mac.c
  23. @@ -2469,7 +2469,7 @@ static void ath10k_peer_assoc_h_vht(stru
  24. const u16 *vht_mcs_mask;
  25. u8 ampdu_factor;
  26. u8 max_nss, vht_mcs;
  27. - int i;
  28. + int i, nss160;
  29. if (WARN_ON(ath10k_mac_vif_chan(vif, &def)))
  30. return;
  31. @@ -2529,23 +2529,45 @@ static void ath10k_peer_assoc_h_vht(stru
  32. __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
  33. arg->peer_vht_rates.tx_mcs_set = ath10k_peer_assoc_h_vht_limit(
  34. __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
  35. + arg->peer_bw_rxnss_override = 0;
  36. + nss160 = 1; /* 1x1 default config for VHT160 */
  37. - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
  38. - sta->addr, arg->peer_max_mpdu, arg->peer_flags);
  39. + /* only local 4x4 configuration do support 2x2 for VHT160,
  40. + * everything else must use 1x1
  41. + */
  42. - if (arg->peer_vht_rates.rx_max_rate &&
  43. - (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) {
  44. - switch (arg->peer_vht_rates.rx_max_rate) {
  45. - case 1560:
  46. - /* Must be 2x2 at 160Mhz is all it can do. */
  47. - arg->peer_bw_rxnss_override = 2;
  48. - break;
  49. - case 780:
  50. - /* Can only do 1x1 at 160Mhz (Long Guard Interval) */
  51. - arg->peer_bw_rxnss_override = 1;
  52. - break;
  53. - }
  54. + if (ar->cfg_rx_chainmask == 15)
  55. + nss160 = arg->peer_num_spatial_streams <= 2 ? 1 : 2;
  56. +
  57. + /* if peer provides 1x1 nss160 information using max rate
  58. + * vht information, we reduce local nss160 to 1x1.
  59. + * consider that it has been observed that some client
  60. + * devices provide zero here, no matter which transmission
  61. + * rate is possible. in that case the local nss configuration
  62. + * will be used at maxmimum configuration possible. (see above)
  63. + */
  64. +
  65. + if (arg->peer_vht_rates.rx_max_rate == 780)
  66. + nss160 = 1;
  67. +
  68. + /* in case if peer is connected with vht160 or vht80+80,
  69. + * we need to properly adjust rxnss parameters otherwise
  70. + * firmware will raise a assert
  71. + */
  72. + switch (arg->peer_phymode) {
  73. + case MODE_11AC_VHT80_80:
  74. + arg->peer_bw_rxnss_override = BW_NSS_FWCONF_80_80(nss160);
  75. + /* fall through */
  76. + case MODE_11AC_VHT160:
  77. + arg->peer_bw_rxnss_override |= BW_NSS_FWCONF_160(nss160);
  78. + break;
  79. + default:
  80. + break;
  81. }
  82. +
  83. + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x peer_bw_rxnss_override 0x%x\n",
  84. + sta->addr, arg->peer_max_mpdu, arg->peer_flags,
  85. + arg->peer_bw_rxnss_override);
  86. }
  87. static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
  88. @@ -2697,9 +2719,9 @@ static int ath10k_peer_assoc_prepare(str
  89. ath10k_peer_assoc_h_crypto(ar, vif, sta, arg);
  90. ath10k_peer_assoc_h_rates(ar, vif, sta, arg);
  91. ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
  92. + ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
  93. ath10k_peer_assoc_h_vht(ar, vif, sta, arg);
  94. ath10k_peer_assoc_h_qos(ar, vif, sta, arg);
  95. - ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
  96. return 0;
  97. }
  98. --- a/drivers/net/wireless/ath/ath10k/wmi.c
  99. +++ b/drivers/net/wireless/ath/ath10k/wmi.c
  100. @@ -7357,12 +7357,7 @@ ath10k_wmi_peer_assoc_fill_10_4(struct a
  101. struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
  102. ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
  103. - if (arg->peer_bw_rxnss_override)
  104. - cmd->peer_bw_rxnss_override =
  105. - __cpu_to_le32((arg->peer_bw_rxnss_override - 1) |
  106. - BIT(PEER_BW_RXNSS_OVERRIDE_OFFSET));
  107. - else
  108. - cmd->peer_bw_rxnss_override = 0;
  109. + cmd->peer_bw_rxnss_override = __cpu_to_le32(arg->peer_bw_rxnss_override);
  110. }
  111. static int
  112. --- a/drivers/net/wireless/ath/ath10k/wmi.h
  113. +++ b/drivers/net/wireless/ath/ath10k/wmi.h
  114. @@ -6357,7 +6357,19 @@ struct wmi_10_2_peer_assoc_complete_cmd
  115. __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
  116. } __packed;
  117. -#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31
  118. +#define BW_NSS_FWCONF_MAP_ENABLE BIT(31)
  119. +#define BW_NSS_FWCONF_MAP_160MHZ_LSB (0)
  120. +#define BW_NSS_FWCONF_MAP_160MHZ_MASK (0x00000007)
  121. +#define BW_NSS_FWCONF_MAP_80_80MHZ_LSB (3)
  122. +#define BW_NSS_FWCONF_MAP_80_80MHZ_MASK (0x00000038)
  123. +#define BW_NSS_FWCONF_MAP_MASK (0x0000003F)
  124. +
  125. +#define GET_BW_NSS_FWCONF_160(x) (MS(x, BW_NSS_FWCONF_MAP_160MHZ) + 1)
  126. +#define GET_BW_NSS_FWCONF_80_80(x) (MS(x, BW_NSS_FWCONF_MAP_80_80MHZ) + 1)
  127. +
  128. +/* Values defined to set 160 MHz Bandwidth NSS Mapping into FW*/
  129. +#define BW_NSS_FWCONF_160(x) (BW_NSS_FWCONF_MAP_ENABLE | SM(x - 1, BW_NSS_FWCONF_MAP_160MHZ))
  130. +#define BW_NSS_FWCONF_80_80(x) (BW_NSS_FWCONF_MAP_ENABLE | SM(x - 1, BW_NSS_FWCONF_MAP_80_80MHZ))
  131. struct wmi_10_4_peer_assoc_complete_cmd {
  132. struct wmi_10_2_peer_assoc_complete_cmd cmd;