History

Merge tag 'wireless-next-2026-03-26' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next

Johannes Berg says: ==================== A fairly big set of changes all over, notably with: - cfg80211: new APIs for NAN (Neighbor Aware Networking, aka Wi-Fi Aware) so less work must be in firmware - mt76: - mt7996/mt7925 MLO fixes/improvements - mt7996 NPU support (HW eth/wifi traffic offload) - iwlwifi: UNII-9 and continuing UHR work * tag 'wireless-next-2026-03-26' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (230 commits) wifi: mac80211: ignore reserved bits in reconfiguration status wifi: cfg80211: allow protected action frame TX for NAN wifi: ieee80211: Add some missing NAN definitions wifi: nl80211: Add a notification to notify NAN channel evacuation wifi: nl80211: add NL80211_CMD_NAN_ULW_UPDATE notification wifi: nl80211: allow reporting spurious NAN Data frames wifi: cfg80211: allow ToDS=0/FromDS=0 data frames on NAN data interfaces wifi: nl80211: define an API for configuring the NAN peer's schedule wifi: nl80211: add support for NAN stations wifi: cfg80211: separately store HT, VHT and HE capabilities for NAN wifi: cfg80211: add support for NAN data interface wifi: cfg80211: make sure NAN chandefs are valid wifi: cfg80211: Add an API to configure local NAN schedule wifi: mac80211: cleanup error path of ieee80211_do_open wifi: mac80211: extract channel logic from link logic wifi: iwlwifi: mld: set RX_FLAG_RADIOTAP_TLV_AT_END generically wifi: iwlwifi: reduce the number of prints upon firmware crash wifi: iwlwifi: fix the description of SESSION_PROTECTION_CMD wifi: iwlwifi: mld: introduce iwl_mld_vif_fw_id_valid wifi: iwlwifi: mld: block EMLSR during TDLS connections ... ====================

Jakub Kicinski committed 7 months ago

Commit dbd94b92 parents 7d89349 7dd6f81166 files · +7113 −2303Browse files

Unified · Split

166 files
  1. drivers/net/wireless/ath/ath10k/usb.c +2 −6
  2. drivers/net/wireless/ath/ath12k/ahb.h +2 −2
  3. drivers/net/wireless/ath/ath12k/core.h +1 −1
  4. drivers/net/wireless/ath/ath12k/dp_htt.c +13 −11
  5. drivers/net/wireless/ath/ath12k/hal.h +19 −12
  6. drivers/net/wireless/ath/ath12k/mac.c +43 −24
  7. drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c +60 −16
  8. drivers/net/wireless/ath/ath12k/wmi.c +27 −31
  9. drivers/net/wireless/ath/ath12k/wmi.h +9 −5
  10. drivers/net/wireless/ath/ath6kl/usb.c +4 −12
  11. drivers/net/wireless/ath/ath6kl/wmi.h +0 −11
  12. drivers/net/wireless/ath/ath9k/hif_usb.c +0 −4
  13. drivers/net/wireless/broadcom/b43/dma.c +8 −10
  14. drivers/net/wireless/broadcom/b43/dma.h +2 −2
  15. drivers/net/wireless/intel/iwlwifi/cfg/bz.c +1 −1
  16. drivers/net/wireless/intel/iwlwifi/cfg/dr.c +1 −1
  17. drivers/net/wireless/intel/iwlwifi/cfg/sc.c +1 −1
  18. drivers/net/wireless/intel/iwlwifi/fw/acpi.c +117 −15
  19. drivers/net/wireless/intel/iwlwifi/fw/acpi.h +19 −9
  20. drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +2 −1
  21. drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +156 −11
  22. drivers/net/wireless/intel/iwlwifi/fw/api/mac.h +2 −4
  23. drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +14 −4
  24. drivers/net/wireless/intel/iwlwifi/fw/api/power.h +36 −1
  25. drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +45 −0
  26. drivers/net/wireless/intel/iwlwifi/fw/api/stats.h +2 −3
  27. drivers/net/wireless/intel/iwlwifi/fw/dbg.c +2 −2
  28. drivers/net/wireless/intel/iwlwifi/fw/dump.c +1 −68
  29. drivers/net/wireless/intel/iwlwifi/fw/file.h +15 −0
  30. drivers/net/wireless/intel/iwlwifi/fw/img.c +31 −1
  31. drivers/net/wireless/intel/iwlwifi/fw/img.h +8 −0
  32. drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +25 −126
  33. drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +7 −7
  34. drivers/net/wireless/intel/iwlwifi/fw/runtime.h +6 −4
  35. drivers/net/wireless/intel/iwlwifi/fw/uefi.c +202 −34
  36. drivers/net/wireless/intel/iwlwifi/fw/uefi.h +110 −31
  37. drivers/net/wireless/intel/iwlwifi/iwl-config.h +0 −1
  38. drivers/net/wireless/intel/iwlwifi/iwl-drv.c +22 −1
  39. drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +8 −1
  40. drivers/net/wireless/intel/iwlwifi/iwl-trans.c +5 −5
  41. drivers/net/wireless/intel/iwlwifi/iwl-trans.h +19 −1
  42. drivers/net/wireless/intel/iwlwifi/mld/constants.h +0 −1
  43. drivers/net/wireless/intel/iwlwifi/mld/fw.c +1 −1
  44. drivers/net/wireless/intel/iwlwifi/mld/iface.c +17 −5
  45. drivers/net/wireless/intel/iwlwifi/mld/iface.h +12 −3
  46. drivers/net/wireless/intel/iwlwifi/mld/link.c +1 −1
  47. drivers/net/wireless/intel/iwlwifi/mld/link.h +2 −0
  48. drivers/net/wireless/intel/iwlwifi/mld/low_latency.c +9 −4
  49. drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +48 −4
  50. drivers/net/wireless/intel/iwlwifi/mld/mld.h +3 −3
  51. drivers/net/wireless/intel/iwlwifi/mld/mlo.c +2 −2
  52. drivers/net/wireless/intel/iwlwifi/mld/nan.h +4 −1
  53. drivers/net/wireless/intel/iwlwifi/mld/phy.h +2 −2
  54. drivers/net/wireless/intel/iwlwifi/mld/power.c +4 −1
  55. drivers/net/wireless/intel/iwlwifi/mld/ptp.c +3 −1
  56. drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +148 −30
  57. drivers/net/wireless/intel/iwlwifi/mld/regulatory.h +1 −1
  58. drivers/net/wireless/intel/iwlwifi/mld/rx.c +14 −11
  59. drivers/net/wireless/intel/iwlwifi/mld/scan.c +169 −55
  60. drivers/net/wireless/intel/iwlwifi/mld/scan.h +2 −0
  61. drivers/net/wireless/intel/iwlwifi/mld/sta.c +40 −10
  62. drivers/net/wireless/intel/iwlwifi/mld/sta.h +2 −2
  63. drivers/net/wireless/intel/iwlwifi/mld/stats.c +27 −4
  64. drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c +4 −4
  65. drivers/net/wireless/intel/iwlwifi/mld/tlc.c +73 −5
  66. drivers/net/wireless/intel/iwlwifi/mld/tlc.h +3 −0
  67. drivers/net/wireless/intel/iwlwifi/mvm/fw.c +143 −14
  68. drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +4 −3
  69. drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c +0 −46
  70. drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c +9 −9
  71. drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +0 −132
  72. drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +3 −288
  73. drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +0 −5
  74. drivers/net/wireless/intel/iwlwifi/mvm/ptp.c +3 −1
  75. drivers/net/wireless/intel/iwlwifi/mvm/sta.h +0 −4
  76. drivers/net/wireless/intel/iwlwifi/mvm/tdls.c +3 −3
  77. drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c +10 −3
  78. drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +1 −1
  79. drivers/net/wireless/mediatek/mt76/channel.c +25 −14
  80. drivers/net/wireless/mediatek/mt76/dma.c +25 −8
  81. drivers/net/wireless/mediatek/mt76/dma.h +3 −1
  82. drivers/net/wireless/mediatek/mt76/eeprom.c +109 −45
  83. drivers/net/wireless/mediatek/mt76/mac80211.c +228 −2
  84. drivers/net/wireless/mediatek/mt76/mcu.c +1 −1
  85. drivers/net/wireless/mediatek/mt76/mt76.h +46 −1
  86. drivers/net/wireless/mediatek/mt76/mt7615/mac.c +0 −15
  87. drivers/net/wireless/mediatek/mt76/mt7615/main.c +4 −3
  88. drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +47 −0
  89. drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +2 −3
  90. drivers/net/wireless/mediatek/mt76/mt7615/regs.h +0 −2
  91. drivers/net/wireless/mediatek/mt76/mt76_connac.h +9 −2
  92. drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +18 −10
  93. drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +29 −17
  94. drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +14 −1
  95. drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +1 −0
  96. drivers/net/wireless/mediatek/mt76/mt7915/init.c +1 −0
  97. drivers/net/wireless/mediatek/mt76/mt7915/mac.c +0 −13
  98. drivers/net/wireless/mediatek/mt76/mt7915/main.c +6 −3
  99. drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +65 −1
  100. drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +11 −0
  101. drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +4 −0
  102. drivers/net/wireless/mediatek/mt76/mt7921/init.c +3 −1
  103. drivers/net/wireless/mediatek/mt76/mt7921/main.c +20 −9
  104. drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +3 −0
  105. drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +16 −0
  106. drivers/net/wireless/mediatek/mt76/mt7921/pci.c +56 −14
  107. drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +3 −3
  108. drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +4 −0
  109. drivers/net/wireless/mediatek/mt76/mt7925/init.c +2 −0
  110. drivers/net/wireless/mediatek/mt76/mt7925/mac.c +12 −6
  111. drivers/net/wireless/mediatek/mt76/mt7925/main.c +324 −66
  112. drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +106 −88
  113. drivers/net/wireless/mediatek/mt76/mt7925/mcu.h +7 −0
  114. drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +8 −5
  115. drivers/net/wireless/mediatek/mt76/mt7925/regd.c +2 −1
  116. drivers/net/wireless/mediatek/mt76/mt792x.h +7 −0
  117. drivers/net/wireless/mediatek/mt76/mt792x_core.c +10 −4
  118. drivers/net/wireless/mediatek/mt76/mt792x_dma.c +17 −1
  119. drivers/net/wireless/mediatek/mt76/mt792x_mac.c +1 −1
  120. drivers/net/wireless/mediatek/mt76/mt792x_regs.h +6 −0
  121. drivers/net/wireless/mediatek/mt76/mt792x_usb.c +43 −8
  122. drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c +30 −6
  123. drivers/net/wireless/mediatek/mt76/mt7996/dma.c +128 −76
  124. drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c +37 −27
  125. drivers/net/wireless/mediatek/mt76/mt7996/init.c +91 −19
  126. drivers/net/wireless/mediatek/mt76/mt7996/mac.c +50 −111
  127. drivers/net/wireless/mediatek/mt76/mt7996/mac.h +0 −5
  128. drivers/net/wireless/mediatek/mt76/mt7996/main.c +323 −94
  129. drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +685 −138
  130. drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +103 −9
  131. drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +63 −7
  132. drivers/net/wireless/mediatek/mt76/mt7996/npu.c +372 −93
  133. drivers/net/wireless/mediatek/mt76/mt7996/regs.h +11 −0
  134. drivers/net/wireless/mediatek/mt76/npu.c +32 −5
  135. drivers/net/wireless/mediatek/mt76/scan.c +61 −9
  136. drivers/net/wireless/mediatek/mt76/tx.c +31 −3
  137. drivers/net/wireless/mediatek/mt7601u/mcu.c +14 −1
  138. drivers/net/wireless/mediatek/mt7601u/usb.h +1 −0
  139. drivers/net/wireless/virtual/mac80211_hwsim.c +35 −0
  140. include/linux/ieee80211-nan.h +6 −1
  141. include/linux/ieee80211.h +7 −0
  142. include/net/cfg80211.h +258 −7
  143. include/uapi/linux/nl80211.h +229 −3
  144. net/mac80211/cfg.c +3 −1
  145. net/mac80211/chan.c +123 −76
  146. net/mac80211/he.c +24 −13
  147. net/mac80211/ht.c +3 −3
  148. net/mac80211/ibss.c +3 −1
  149. net/mac80211/ieee80211_i.h +11 −1
  150. net/mac80211/iface.c +18 −10
  151. net/mac80211/mesh_plink.c +2 −1
  152. net/mac80211/mlme.c +10 −7
  153. net/mac80211/rx.c +2 −0
  154. net/mac80211/trace.h +2 −3
  155. net/mac80211/util.c +1 −0
  156. net/mac80211/vht.c +18 −15
  157. net/wireless/chan.c +4 −2
  158. net/wireless/core.c +120 −10
  159. net/wireless/core.h +10 −0
  160. net/wireless/mlme.c +9 −4
  161. net/wireless/nl80211.c +877 −28
  162. net/wireless/rdev-ops.h +32 −0
  163. net/wireless/reg.c +21 −6
  164. net/wireless/sysfs.c +14 −13
  165. net/wireless/trace.h +105 −0
  166. net/wireless/util.c +22 −6
drivers/net/wireless/ath/ath10k/usb.c+2−6
@@ -1016,7 +1016,6 @@ static int ath10k_usb_probe(struct usb_interface *interface, · 1015 unmodified lines
1016 1016
1017 netif_napi_add(ar->napi_dev, &ar->napi, ath10k_usb_napi_poll);1017 netif_napi_add(ar->napi_dev, &ar->napi, ath10k_usb_napi_poll);
1018 1018
1019 usb_get_dev(dev);
1020 vendor_id = le16_to_cpu(dev->descriptor.idVendor);1019 vendor_id = le16_to_cpu(dev->descriptor.idVendor);
1021 product_id = le16_to_cpu(dev->descriptor.idProduct);1020 product_id = le16_to_cpu(dev->descriptor.idProduct);
1022 1021
@@ -1055,12 +1054,10 @@ err_usb_destroy: · 32 unmodified lines
1055err:1054err:
1056 ath10k_core_destroy(ar);1055 ath10k_core_destroy(ar);
1057 1056
1058 usb_put_dev(dev);
1059
1060 return ret;1057 return ret;
1061}1058}
1062 1059
1063static void ath10k_usb_remove(struct usb_interface *interface)1060static void ath10k_usb_disconnect(struct usb_interface *interface)
1064{1061{
1065 struct ath10k_usb *ar_usb;1062 struct ath10k_usb *ar_usb;
1066 1063
@@ -1071,7 +1068,6 @@ static void ath10k_usb_remove(struct usb_interface *interface) · 4 unmodified lines
1071 ath10k_core_unregister(ar_usb->ar);1068 ath10k_core_unregister(ar_usb->ar);
1072 netif_napi_del(&ar_usb->ar->napi);1069 netif_napi_del(&ar_usb->ar->napi);
1073 ath10k_usb_destroy(ar_usb->ar);1070 ath10k_usb_destroy(ar_usb->ar);
1074 usb_put_dev(interface_to_usbdev(interface));
1075 ath10k_core_destroy(ar_usb->ar);1071 ath10k_core_destroy(ar_usb->ar);
1076}1072}
1077 1073
@@ -1117,7 +1113,7 @@ static struct usb_driver ath10k_usb_driver = { · 39 unmodified lines
1117 .probe = ath10k_usb_probe,1113 .probe = ath10k_usb_probe,
1118 .suspend = ath10k_usb_pm_suspend,1114 .suspend = ath10k_usb_pm_suspend,
1119 .resume = ath10k_usb_pm_resume,1115 .resume = ath10k_usb_pm_resume,
1120 .disconnect = ath10k_usb_remove,1116 .disconnect = ath10k_usb_disconnect,
1121 .id_table = ath10k_usb_ids,1117 .id_table = ath10k_usb_ids,
1122 .supports_autosuspend = true,1118 .supports_autosuspend = true,
1123 .disable_hub_initiated_lpm = 1,1119 .disable_hub_initiated_lpm = 1,
drivers/net/wireless/ath/ath12k/ahb.h+2−2
@@ -21,8 +21,8 @@ · 20 unmodified lines
21#define ATH12K_ROOTPD_READY_TIMEOUT (5 * HZ)21#define ATH12K_ROOTPD_READY_TIMEOUT (5 * HZ)
22#define ATH12K_RPROC_AFTER_POWERUP QCOM_SSR_AFTER_POWERUP22#define ATH12K_RPROC_AFTER_POWERUP QCOM_SSR_AFTER_POWERUP
23#define ATH12K_AHB_FW_PREFIX "q6_fw"23#define ATH12K_AHB_FW_PREFIX "q6_fw"
24#define ATH12K_AHB_FW_SUFFIX ".mdt"24#define ATH12K_AHB_FW_SUFFIX ".mbn"
25#define ATH12K_AHB_FW2 "iu_fw.mdt"25#define ATH12K_AHB_FW2 "iu_fw.mbn"
26#define ATH12K_AHB_UPD_SWID 0x1226#define ATH12K_AHB_UPD_SWID 0x12
27#define ATH12K_USERPD_SPAWN_TIMEOUT (5 * HZ)27#define ATH12K_USERPD_SPAWN_TIMEOUT (5 * HZ)
28#define ATH12K_USERPD_READY_TIMEOUT (10 * HZ)28#define ATH12K_USERPD_READY_TIMEOUT (10 * HZ)
drivers/net/wireless/ath/ath12k/core.h+1−1
@@ -523,7 +523,7 @@ struct ath12k_sta { · 522 unmodified lines
523 u16 links_map;523 u16 links_map;
524 u8 assoc_link_id;524 u8 assoc_link_id;
525 u16 ml_peer_id;525 u16 ml_peer_id;
526 u8 num_peer;526 u16 free_logical_link_idx_map;
527 527
528 enum ieee80211_sta_state state;528 enum ieee80211_sta_state state;
529};529};
drivers/net/wireless/ath/ath12k/dp_htt.c+13−11
@@ -205,16 +205,9 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, · 204 unmodified lines
205 if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE)))205 if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE)))
206 return;206 return;
207 207
208 if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {208 if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON))
209 is_ampdu =209 is_ampdu =
210 HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags);210 HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags);
211 tx_retry_failed =
212 __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -
213 __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);
214 tx_retry_count =
215 HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
216 HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
217 }
218 211
219 if (usr_stats->tlv_flags &212 if (usr_stats->tlv_flags &
220 BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) {213 BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) {
@@ -223,10 +216,19 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev, · 2 unmodified lines
223 HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M);216 HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M);
224 tid = le32_get_bits(usr_stats->ack_ba.info,217 tid = le32_get_bits(usr_stats->ack_ba.info,
225 HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM);218 HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM);
226 }
227 219
228 if (common->fes_duration_us)220 if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {
229 tx_duration = le32_to_cpu(common->fes_duration_us);221 tx_retry_failed =
222 __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -
223 __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);
224 tx_retry_count =
225 HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
226 HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
227 }
228
229 if (common->fes_duration_us)
230 tx_duration = le32_to_cpu(common->fes_duration_us);
231 }
230 232
231 user_rate = &usr_stats->rate;233 user_rate = &usr_stats->rate;
232 flags = HTT_USR_RATE_PREAMBLE(user_rate->rate_flags);234 flags = HTT_USR_RATE_PREAMBLE(user_rate->rate_flags);
drivers/net/wireless/ath/ath12k/hal.h+19−12
@@ -268,21 +268,28 @@ enum hal_rx_reception_type { · 267 unmodified lines
268};268};
269 269
270enum hal_rx_legacy_rate {270enum hal_rx_legacy_rate {
271 HAL_RX_LEGACY_RATE_1_MBPS,271 HAL_RX_LEGACY_RATE_LP_1_MBPS,
272 HAL_RX_LEGACY_RATE_2_MBPS,272 HAL_RX_LEGACY_RATE_LP_2_MBPS,
273 HAL_RX_LEGACY_RATE_5_5_MBPS,273 HAL_RX_LEGACY_RATE_LP_5_5_MBPS,
274 HAL_RX_LEGACY_RATE_6_MBPS,274 HAL_RX_LEGACY_RATE_LP_11_MBPS,
275 HAL_RX_LEGACY_RATE_9_MBPS,275 HAL_RX_LEGACY_RATE_SP_2_MBPS,
276 HAL_RX_LEGACY_RATE_11_MBPS,276 HAL_RX_LEGACY_RATE_SP_5_5_MBPS,
277 HAL_RX_LEGACY_RATE_12_MBPS,277 HAL_RX_LEGACY_RATE_SP_11_MBPS,
278 HAL_RX_LEGACY_RATE_18_MBPS,
279 HAL_RX_LEGACY_RATE_24_MBPS,
280 HAL_RX_LEGACY_RATE_36_MBPS,
281 HAL_RX_LEGACY_RATE_48_MBPS,
282 HAL_RX_LEGACY_RATE_54_MBPS,
283 HAL_RX_LEGACY_RATE_INVALID,278 HAL_RX_LEGACY_RATE_INVALID,
284};279};
285 280
281enum hal_rx_legacy_rates_ofdm {
282 HAL_RX_LEGACY_RATE_OFDM_48_MBPS,
283 HAL_RX_LEGACY_RATE_OFDM_24_MBPS,
284 HAL_RX_LEGACY_RATE_OFDM_12_MBPS,
285 HAL_RX_LEGACY_RATE_OFDM_6_MBPS,
286 HAL_RX_LEGACY_RATE_OFDM_54_MBPS,
287 HAL_RX_LEGACY_RATE_OFDM_36_MBPS,
288 HAL_RX_LEGACY_RATE_OFDM_18_MBPS,
289 HAL_RX_LEGACY_RATE_OFDM_9_MBPS,
290 HAL_RX_LEGACY_RATE_OFDM_INVALID,
291};
292
286enum hal_ring_type {293enum hal_ring_type {
287 HAL_REO_DST,294 HAL_REO_DST,
288 HAL_REO_EXCEPTION,295 HAL_REO_EXCEPTION,
drivers/net/wireless/ath/ath12k/mac.c+43−24
@@ -164,30 +164,31 @@ static const struct ieee80211_channel ath12k_6ghz_channels[] = { · 163 unmodified lines
164 CHAN6G(233, 7115, 0),164 CHAN6G(233, 7115, 0),
165};165};
166 166
167#define ATH12K_MAC_RATE_A_M(bps, code) \
168 { .bitrate = (bps), .hw_value = (code),\
169 .flags = IEEE80211_RATE_MANDATORY_A }
170
171#define ATH12K_MAC_RATE_B(bps, code, code_short) \
172 { .bitrate = (bps), .hw_value = (code), .hw_value_short = (code_short),\
173 .flags = IEEE80211_RATE_SHORT_PREAMBLE }
174
167static struct ieee80211_rate ath12k_legacy_rates[] = {175static struct ieee80211_rate ath12k_legacy_rates[] = {
168 { .bitrate = 10,176 { .bitrate = 10,
169 .hw_value = ATH12K_HW_RATE_CCK_LP_1M },177 .hw_value = ATH12K_HW_RATE_CCK_LP_1M },
170 { .bitrate = 20,178 ATH12K_MAC_RATE_B(20, ATH12K_HW_RATE_CCK_LP_2M,
171 .hw_value = ATH12K_HW_RATE_CCK_LP_2M,179 ATH12K_HW_RATE_CCK_SP_2M),
172 .hw_value_short = ATH12K_HW_RATE_CCK_SP_2M,180 ATH12K_MAC_RATE_B(55, ATH12K_HW_RATE_CCK_LP_5_5M,
173 .flags = IEEE80211_RATE_SHORT_PREAMBLE },181 ATH12K_HW_RATE_CCK_SP_5_5M),
174 { .bitrate = 55,182 ATH12K_MAC_RATE_B(110, ATH12K_HW_RATE_CCK_LP_11M,
175 .hw_value = ATH12K_HW_RATE_CCK_LP_5_5M,183 ATH12K_HW_RATE_CCK_SP_11M),
176 .hw_value_short = ATH12K_HW_RATE_CCK_SP_5_5M,184 ATH12K_MAC_RATE_A_M(60, ATH12K_HW_RATE_OFDM_6M),
177 .flags = IEEE80211_RATE_SHORT_PREAMBLE },185 ATH12K_MAC_RATE_A_M(90, ATH12K_HW_RATE_OFDM_9M),
178 { .bitrate = 110,186 ATH12K_MAC_RATE_A_M(120, ATH12K_HW_RATE_OFDM_12M),
179 .hw_value = ATH12K_HW_RATE_CCK_LP_11M,187 ATH12K_MAC_RATE_A_M(180, ATH12K_HW_RATE_OFDM_18M),
180 .hw_value_short = ATH12K_HW_RATE_CCK_SP_11M,188 ATH12K_MAC_RATE_A_M(240, ATH12K_HW_RATE_OFDM_24M),
181 .flags = IEEE80211_RATE_SHORT_PREAMBLE },189 ATH12K_MAC_RATE_A_M(360, ATH12K_HW_RATE_OFDM_36M),
182 190 ATH12K_MAC_RATE_A_M(480, ATH12K_HW_RATE_OFDM_48M),
183 { .bitrate = 60, .hw_value = ATH12K_HW_RATE_OFDM_6M },191 ATH12K_MAC_RATE_A_M(540, ATH12K_HW_RATE_OFDM_54M),
184 { .bitrate = 90, .hw_value = ATH12K_HW_RATE_OFDM_9M },
185 { .bitrate = 120, .hw_value = ATH12K_HW_RATE_OFDM_12M },
186 { .bitrate = 180, .hw_value = ATH12K_HW_RATE_OFDM_18M },
187 { .bitrate = 240, .hw_value = ATH12K_HW_RATE_OFDM_24M },
188 { .bitrate = 360, .hw_value = ATH12K_HW_RATE_OFDM_36M },
189 { .bitrate = 480, .hw_value = ATH12K_HW_RATE_OFDM_48M },
190 { .bitrate = 540, .hw_value = ATH12K_HW_RATE_OFDM_54M },
191};192};
192 193
193static const int194static const int
@@ -732,11 +733,17 @@ u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband, · 538 unmodified lines
732 if (ath12k_mac_bitrate_is_cck(rate->bitrate) != cck)733 if (ath12k_mac_bitrate_is_cck(rate->bitrate) != cck)
733 continue;734 continue;
734 735
735 if (rate->hw_value == hw_rate)736 /* To handle 802.11a PPDU type */
737 if ((!cck) && (rate->hw_value == hw_rate) &&
738 (rate->flags & IEEE80211_RATE_MANDATORY_A))
736 return i;739 return i;
740 /* To handle 802.11b short PPDU type */
737 else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&741 else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
738 rate->hw_value_short == hw_rate)742 rate->hw_value_short == hw_rate)
739 return i;743 return i;
744 /* To handle 802.11b long PPDU type */
745 else if (rate->hw_value == hw_rate)
746 return i;
740 }747 }
741 748
742 return 0;749 return 0;
@@ -6786,6 +6793,8 @@ static void ath12k_mac_free_unassign_link_sta(struct ath12k_hw *ah, · 6043 unmodified lines
6786 return;6793 return;
6787 6794
6788 ahsta->links_map &= ~BIT(link_id);6795 ahsta->links_map &= ~BIT(link_id);
6796 ahsta->free_logical_link_idx_map |= BIT(arsta->link_idx);
6797
6789 rcu_assign_pointer(ahsta->link[link_id], NULL);6798 rcu_assign_pointer(ahsta->link[link_id], NULL);
6790 synchronize_rcu();6799 synchronize_rcu();
6791 6800
@@ -7104,6 +7113,7 @@ static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah, · 312 unmodified lines
7104 struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);7113 struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
7105 struct ieee80211_link_sta *link_sta;7114 struct ieee80211_link_sta *link_sta;
7106 struct ath12k_link_vif *arvif;7115 struct ath12k_link_vif *arvif;
7116 int link_idx;
7107 7117
7108 lockdep_assert_wiphy(ah->hw->wiphy);7118 lockdep_assert_wiphy(ah->hw->wiphy);
7109 7119
@@ -7122,8 +7132,16 @@ static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah, · 12 unmodified lines
7122 7132
7123 ether_addr_copy(arsta->addr, link_sta->addr);7133 ether_addr_copy(arsta->addr, link_sta->addr);
7124 7134
7125 /* logical index of the link sta in order of creation */7135 if (!ahsta->free_logical_link_idx_map)
7126 arsta->link_idx = ahsta->num_peer++;7136 return -ENOSPC;
7137
7138 /*
7139 * Allocate a logical link index by selecting the first available bit
7140 * from the free logical index map
7141 */
7142 link_idx = __ffs(ahsta->free_logical_link_idx_map);
7143 ahsta->free_logical_link_idx_map &= ~BIT(link_idx);
7144 arsta->link_idx = link_idx;
7127 7145
7128 arsta->link_id = link_id;7146 arsta->link_id = link_id;
7129 ahsta->links_map |= BIT(arsta->link_id);7147 ahsta->links_map |= BIT(arsta->link_id);
@@ -7632,6 +7650,7 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, · 502 unmodified lines
7632 if (old_state == IEEE80211_STA_NOTEXIST &&7650 if (old_state == IEEE80211_STA_NOTEXIST &&
7633 new_state == IEEE80211_STA_NONE) {7651 new_state == IEEE80211_STA_NONE) {
7634 memset(ahsta, 0, sizeof(*ahsta));7652 memset(ahsta, 0, sizeof(*ahsta));
7653 ahsta->free_logical_link_idx_map = U16_MAX;
7635 7654
7636 arsta = &ahsta->deflink;7655 arsta = &ahsta->deflink;
7637 7656
drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c+60−16
@@ -405,6 +405,42 @@ ath12k_wifi7_dp_mon_hal_rx_parse_user_info(const struct hal_receive_user_info *r · 404 unmodified lines
405 }405 }
406}406}
407 407
408static __always_inline u8
409ath12k_wifi7_hal_mon_map_legacy_rate_to_hw_rate(u8 rate)
410{
411 u8 ath12k_rate;
412
413 /* Map hal_rx_legacy_rate to ath12k_hw_rate_cck */
414 switch (rate) {
415 case HAL_RX_LEGACY_RATE_LP_1_MBPS:
416 ath12k_rate = ATH12K_HW_RATE_CCK_LP_1M;
417 break;
418 case HAL_RX_LEGACY_RATE_LP_2_MBPS:
419 ath12k_rate = ATH12K_HW_RATE_CCK_LP_2M;
420 break;
421 case HAL_RX_LEGACY_RATE_LP_5_5_MBPS:
422 ath12k_rate = ATH12K_HW_RATE_CCK_LP_5_5M;
423 break;
424 case HAL_RX_LEGACY_RATE_LP_11_MBPS:
425 ath12k_rate = ATH12K_HW_RATE_CCK_LP_11M;
426 break;
427 case HAL_RX_LEGACY_RATE_SP_2_MBPS:
428 ath12k_rate = ATH12K_HW_RATE_CCK_SP_2M;
429 break;
430 case HAL_RX_LEGACY_RATE_SP_5_5_MBPS:
431 ath12k_rate = ATH12K_HW_RATE_CCK_SP_5_5M;
432 break;
433 case HAL_RX_LEGACY_RATE_SP_11_MBPS:
434 ath12k_rate = ATH12K_HW_RATE_CCK_SP_11M;
435 break;
436 default:
437 ath12k_rate = rate;
438 break;
439 }
440
441 return ath12k_rate;
442}
443
408static void444static void
409ath12k_wifi7_dp_mon_parse_l_sig_b(const struct hal_rx_lsig_b_info *lsigb,445ath12k_wifi7_dp_mon_parse_l_sig_b(const struct hal_rx_lsig_b_info *lsigb,
410 struct hal_rx_mon_ppdu_info *ppdu_info)446 struct hal_rx_mon_ppdu_info *ppdu_info)
@@ -415,25 +451,32 @@ ath12k_wifi7_dp_mon_parse_l_sig_b(const struct hal_rx_lsig_b_info *lsigb, · 4 unmodified lines
415 rate = u32_get_bits(info0, HAL_RX_LSIG_B_INFO_INFO0_RATE);451 rate = u32_get_bits(info0, HAL_RX_LSIG_B_INFO_INFO0_RATE);
416 switch (rate) {452 switch (rate) {
417 case 1:453 case 1:
418 rate = HAL_RX_LEGACY_RATE_1_MBPS;454 rate = HAL_RX_LEGACY_RATE_LP_1_MBPS;
419 break;455 break;
420 case 2:456 case 2:
421 case 5:457 rate = HAL_RX_LEGACY_RATE_LP_2_MBPS;
422 rate = HAL_RX_LEGACY_RATE_2_MBPS;
423 break;458 break;
424 case 3:459 case 3:
425 case 6:460 rate = HAL_RX_LEGACY_RATE_LP_5_5_MBPS;
426 rate = HAL_RX_LEGACY_RATE_5_5_MBPS;
427 break;461 break;
428 case 4:462 case 4:
463 rate = HAL_RX_LEGACY_RATE_LP_11_MBPS;
464 break;
465 case 5:
466 rate = HAL_RX_LEGACY_RATE_SP_2_MBPS;
467 break;
468 case 6:
469 rate = HAL_RX_LEGACY_RATE_SP_5_5_MBPS;
470 break;
429 case 7:471 case 7:
430 rate = HAL_RX_LEGACY_RATE_11_MBPS;472 rate = HAL_RX_LEGACY_RATE_SP_11_MBPS;
431 break;473 break;
432 default:474 default:
433 rate = HAL_RX_LEGACY_RATE_INVALID;475 rate = HAL_RX_LEGACY_RATE_INVALID;
476 break;
434 }477 }
435 478
436 ppdu_info->rate = rate;479 ppdu_info->rate = ath12k_wifi7_hal_mon_map_legacy_rate_to_hw_rate(rate);
437 ppdu_info->cck_flag = 1;480 ppdu_info->cck_flag = 1;
438}481}
439 482
@@ -447,31 +490,32 @@ ath12k_wifi7_dp_mon_parse_l_sig_a(const struct hal_rx_lsig_a_info *lsiga, · 7 unmodified lines
447 rate = u32_get_bits(info0, HAL_RX_LSIG_A_INFO_INFO0_RATE);490 rate = u32_get_bits(info0, HAL_RX_LSIG_A_INFO_INFO0_RATE);
448 switch (rate) {491 switch (rate) {
449 case 8:492 case 8:
450 rate = HAL_RX_LEGACY_RATE_48_MBPS;493 rate = HAL_RX_LEGACY_RATE_OFDM_48_MBPS;
451 break;494 break;
452 case 9:495 case 9:
453 rate = HAL_RX_LEGACY_RATE_24_MBPS;496 rate = HAL_RX_LEGACY_RATE_OFDM_24_MBPS;
454 break;497 break;
455 case 10:498 case 10:
456 rate = HAL_RX_LEGACY_RATE_12_MBPS;499 rate = HAL_RX_LEGACY_RATE_OFDM_12_MBPS;
457 break;500 break;
458 case 11:501 case 11:
459 rate = HAL_RX_LEGACY_RATE_6_MBPS;502 rate = HAL_RX_LEGACY_RATE_OFDM_6_MBPS;
460 break;503 break;
461 case 12:504 case 12:
462 rate = HAL_RX_LEGACY_RATE_54_MBPS;505 rate = HAL_RX_LEGACY_RATE_OFDM_54_MBPS;
463 break;506 break;
464 case 13:507 case 13:
465 rate = HAL_RX_LEGACY_RATE_36_MBPS;508 rate = HAL_RX_LEGACY_RATE_OFDM_36_MBPS;
466 break;509 break;
467 case 14:510 case 14:
468 rate = HAL_RX_LEGACY_RATE_18_MBPS;511 rate = HAL_RX_LEGACY_RATE_OFDM_18_MBPS;
469 break;512 break;
470 case 15:513 case 15:
471 rate = HAL_RX_LEGACY_RATE_9_MBPS;514 rate = HAL_RX_LEGACY_RATE_OFDM_9_MBPS;
472 break;515 break;
473 default:516 default:
474 rate = HAL_RX_LEGACY_RATE_INVALID;517 rate = HAL_RX_LEGACY_RATE_OFDM_INVALID;
518 break;
475 }519 }
476 520
477 ppdu_info->rate = rate;521 ppdu_info->rate = rate;
drivers/net/wireless/ath/ath12k/wmi.c+27−31
@@ -10017,50 +10017,46 @@ static int ath12k_connect_pdev_htc_service(struct ath12k_base *ab, · 10016 unmodified lines
10017 10017
10018static int10018static int
10019ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,10019ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,
10020 struct wmi_unit_test_cmd ut_cmd,10020 const struct wmi_unit_test_arg *ut)
10021 u32 *test_args)
10022{10021{
10023 struct ath12k_wmi_pdev *wmi = ar->wmi;10022 struct ath12k_wmi_pdev *wmi = ar->wmi;
10024 struct wmi_unit_test_cmd *cmd;10023 struct wmi_unit_test_cmd *cmd;
10024 int buf_len, arg_len;
10025 struct sk_buff *skb;10025 struct sk_buff *skb;
10026 struct wmi_tlv *tlv;10026 struct wmi_tlv *tlv;
10027 __le32 *ut_cmd_args;
10027 void *ptr;10028 void *ptr;
10028 u32 *ut_cmd_args;
10029 int buf_len, arg_len;
10030 int ret;10029 int ret;
10031 int i;10030 int i;
10032 10031
10033 arg_len = sizeof(u32) * le32_to_cpu(ut_cmd.num_args);10032 arg_len = sizeof(*ut_cmd_args) * ut->num_args;
10034 buf_len = sizeof(ut_cmd) + arg_len + TLV_HDR_SIZE;10033 buf_len = sizeof(*cmd) + arg_len + TLV_HDR_SIZE;
10035 10034
10036 skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, buf_len);10035 skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, buf_len);
10037 if (!skb)10036 if (!skb)
10038 return -ENOMEM;10037 return -ENOMEM;
10039 10038
10040 cmd = (struct wmi_unit_test_cmd *)skb->data;10039 ptr = skb->data;
10040 cmd = ptr;
10041 cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_UNIT_TEST_CMD,10041 cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_UNIT_TEST_CMD,
10042 sizeof(ut_cmd));10042 sizeof(*cmd));
10043 10043 cmd->vdev_id = cpu_to_le32(ut->vdev_id);
10044 cmd->vdev_id = ut_cmd.vdev_id;10044 cmd->module_id = cpu_to_le32(ut->module_id);
10045 cmd->module_id = ut_cmd.module_id;10045 cmd->num_args = cpu_to_le32(ut->num_args);
10046 cmd->num_args = ut_cmd.num_args;10046 cmd->diag_token = cpu_to_le32(ut->diag_token);
10047 cmd->diag_token = ut_cmd.diag_token;
10048
10049 ptr = skb->data + sizeof(ut_cmd);
10050 10047
10048 ptr += sizeof(*cmd);
10051 tlv = ptr;10049 tlv = ptr;
10052 tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, arg_len);10050 tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, arg_len);
10053 10051
10054 ptr += TLV_HDR_SIZE;10052 ptr += TLV_HDR_SIZE;
10055
10056 ut_cmd_args = ptr;10053 ut_cmd_args = ptr;
10057 for (i = 0; i < le32_to_cpu(ut_cmd.num_args); i++)10054 for (i = 0; i < ut->num_args; i++)
10058 ut_cmd_args[i] = test_args[i];10055 ut_cmd_args[i] = cpu_to_le32(ut->args[i]);
10059 10056
10060 ath12k_dbg(ar->ab, ATH12K_DBG_WMI,10057 ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
10061 "WMI unit test : module %d vdev %d n_args %d token %d\n",10058 "WMI unit test : module %d vdev %d n_args %d token %d\n",
10062 cmd->module_id, cmd->vdev_id, cmd->num_args,10059 ut->module_id, ut->vdev_id, ut->num_args, ut->diag_token);
10063 cmd->diag_token);
10064 10060
10065 ret = ath12k_wmi_cmd_send(wmi, skb, WMI_UNIT_TEST_CMDID);10061 ret = ath12k_wmi_cmd_send(wmi, skb, WMI_UNIT_TEST_CMDID);
10066 10062
@@ -10076,8 +10072,7 @@ ath12k_wmi_send_unit_test_cmd(struct ath12k *ar, · 9 unmodified lines
10076int ath12k_wmi_simulate_radar(struct ath12k *ar)10072int ath12k_wmi_simulate_radar(struct ath12k *ar)
10077{10073{
10078 struct ath12k_link_vif *arvif;10074 struct ath12k_link_vif *arvif;
10079 u32 dfs_args[DFS_MAX_TEST_ARGS];10075 struct wmi_unit_test_arg wmi_ut = {};
10080 struct wmi_unit_test_cmd wmi_ut;
10081 bool arvif_found = false;10076 bool arvif_found = false;
10082 10077
10083 list_for_each_entry(arvif, &ar->arvifs, list) {10078 list_for_each_entry(arvif, &ar->arvifs, list) {
@@ -10090,22 +10085,23 @@ int ath12k_wmi_simulate_radar(struct ath12k *ar) · 6 unmodified lines
10090 if (!arvif_found)10085 if (!arvif_found)
10091 return -EINVAL;10086 return -EINVAL;
10092 10087
10093 dfs_args[DFS_TEST_CMDID] = 0;10088 wmi_ut.args[DFS_TEST_CMDID] = 0;
10094 dfs_args[DFS_TEST_PDEV_ID] = ar->pdev->pdev_id;10089 wmi_ut.args[DFS_TEST_PDEV_ID] = ar->pdev->pdev_id;
10095 /* Currently we could pass segment_id(b0 - b1), chirp(b2)10090 /*
10091 * Currently we could pass segment_id(b0 - b1), chirp(b2)
10096 * freq offset (b3 - b10) to unit test. For simulation10092 * freq offset (b3 - b10) to unit test. For simulation
10097 * purpose this can be set to 0 which is valid.10093 * purpose this can be set to 0 which is valid.
10098 */10094 */
10099 dfs_args[DFS_TEST_RADAR_PARAM] = 0;10095 wmi_ut.args[DFS_TEST_RADAR_PARAM] = 0;
10100 10096
10101 wmi_ut.vdev_id = cpu_to_le32(arvif->vdev_id);10097 wmi_ut.vdev_id = arvif->vdev_id;
10102 wmi_ut.module_id = cpu_to_le32(DFS_UNIT_TEST_MODULE);10098 wmi_ut.module_id = DFS_UNIT_TEST_MODULE;
10103 wmi_ut.num_args = cpu_to_le32(DFS_MAX_TEST_ARGS);10099 wmi_ut.num_args = DFS_MAX_TEST_ARGS;
10104 wmi_ut.diag_token = cpu_to_le32(DFS_UNIT_TEST_TOKEN);10100 wmi_ut.diag_token = DFS_UNIT_TEST_TOKEN;
10105 10101
10106 ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Triggering Radar Simulation\n");10102 ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Triggering Radar Simulation\n");
10107 10103
10108 return ath12k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args);10104 return ath12k_wmi_send_unit_test_cmd(ar, &wmi_ut);
10109}10105}
10110 10106
10111int ath12k_wmi_send_tpc_stats_request(struct ath12k *ar,10107int ath12k_wmi_send_tpc_stats_request(struct ath12k *ar,
drivers/net/wireless/ath/ath12k/wmi.h+9−5
@@ -4193,7 +4193,6 @@ struct wmi_addba_clear_resp_cmd { · 4192 unmodified lines
4193 struct ath12k_wmi_mac_addr_params peer_macaddr;4193 struct ath12k_wmi_mac_addr_params peer_macaddr;
4194} __packed;4194} __packed;
4195 4195
4196#define DFS_PHYERR_UNIT_TEST_CMD 0
4197#define DFS_UNIT_TEST_MODULE 0x2b4196#define DFS_UNIT_TEST_MODULE 0x2b
4198#define DFS_UNIT_TEST_TOKEN 0xAA4197#define DFS_UNIT_TEST_TOKEN 0xAA
4199 4198
@@ -4204,10 +4203,15 @@ enum dfs_test_args_idx { · 4 unmodified lines
4204 DFS_MAX_TEST_ARGS,4203 DFS_MAX_TEST_ARGS,
4205};4204};
4206 4205
4207struct wmi_dfs_unit_test_arg {4206/* update if another test command requires more */
4208 u32 cmd_id;4207#define WMI_UNIT_TEST_ARGS_MAX DFS_MAX_TEST_ARGS
4209 u32 pdev_id;4208
4210 u32 radar_param;4209struct wmi_unit_test_arg {
4210 u32 vdev_id;
4211 u32 module_id;
4212 u32 diag_token;
4213 u32 num_args;
4214 u32 args[WMI_UNIT_TEST_ARGS_MAX];
4211};4215};
4212 4216
4213struct wmi_unit_test_cmd {4217struct wmi_unit_test_cmd {
drivers/net/wireless/ath/ath6kl/usb.c+4−12
@@ -1124,8 +1124,6 @@ static int ath6kl_usb_probe(struct usb_interface *interface, · 1123 unmodified lines
1124 int vendor_id, product_id;1124 int vendor_id, product_id;
1125 int ret = 0;1125 int ret = 0;
1126 1126
1127 usb_get_dev(dev);
1128
1129 vendor_id = le16_to_cpu(dev->descriptor.idVendor);1127 vendor_id = le16_to_cpu(dev->descriptor.idVendor);
1130 product_id = le16_to_cpu(dev->descriptor.idProduct);1128 product_id = le16_to_cpu(dev->descriptor.idProduct);
1131 1129
@@ -1143,11 +1141,8 @@ static int ath6kl_usb_probe(struct usb_interface *interface, · 11 unmodified lines
1143 ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n");1141 ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n");
1144 1142
1145 ar_usb = ath6kl_usb_create(interface);1143 ar_usb = ath6kl_usb_create(interface);
1146 1144 if (ar_usb == NULL)
1147 if (ar_usb == NULL) {1145 return -ENOMEM;
1148 ret = -ENOMEM;
1149 goto err_usb_put;
1150 }
1151 1146
1152 ar = ath6kl_core_create(&ar_usb->udev->dev);1147 ar = ath6kl_core_create(&ar_usb->udev->dev);
1153 if (ar == NULL) {1148 if (ar == NULL) {
@@ -1176,15 +1171,12 @@ err_core_free: · 22 unmodified lines
1176 ath6kl_core_destroy(ar);1171 ath6kl_core_destroy(ar);
1177err_usb_destroy:1172err_usb_destroy:
1178 ath6kl_usb_destroy(ar_usb);1173 ath6kl_usb_destroy(ar_usb);
1179err_usb_put:
1180 usb_put_dev(dev);
1181 1174
1182 return ret;1175 return ret;
1183}1176}
1184 1177
1185static void ath6kl_usb_remove(struct usb_interface *interface)1178static void ath6kl_usb_disconnect(struct usb_interface *interface)
1186{1179{
1187 usb_put_dev(interface_to_usbdev(interface));
1188 ath6kl_usb_device_detached(interface);1180 ath6kl_usb_device_detached(interface);
1189}1181}
1190 1182
@@ -1235,7 +1227,7 @@ static struct usb_driver ath6kl_usb_driver = { · 44 unmodified lines
1235 .probe = ath6kl_usb_probe,1227 .probe = ath6kl_usb_probe,
1236 .suspend = ath6kl_usb_pm_suspend,1228 .suspend = ath6kl_usb_pm_suspend,
1237 .resume = ath6kl_usb_pm_resume,1229 .resume = ath6kl_usb_pm_resume,
1238 .disconnect = ath6kl_usb_remove,1230 .disconnect = ath6kl_usb_disconnect,
1239 .id_table = ath6kl_usb_ids,1231 .id_table = ath6kl_usb_ids,
1240 .supports_autosuspend = true,1232 .supports_autosuspend = true,
1241 .disable_hub_initiated_lpm = 1,1233 .disable_hub_initiated_lpm = 1,
drivers/net/wireless/ath/ath6kl/wmi.h+0−11
@@ -1630,16 +1630,6 @@ enum wmi_roam_mode { · 1629 unmodified lines
1630 WMI_LOCK_BSS_MODE = 3, /* Lock to the current BSS */1630 WMI_LOCK_BSS_MODE = 3, /* Lock to the current BSS */
1631};1631};
1632 1632
1633struct bss_bias {
1634 u8 bssid[ETH_ALEN];
1635 s8 bias;
1636} __packed;
1637
1638struct bss_bias_info {
1639 u8 num_bss;
1640 struct bss_bias bss_bias[];
1641} __packed;
1642
1643struct low_rssi_scan_params {1633struct low_rssi_scan_params {
1644 __le16 lrssi_scan_period;1634 __le16 lrssi_scan_period;
1645 a_sle16 lrssi_scan_threshold;1635 a_sle16 lrssi_scan_threshold;
@@ -1652,7 +1642,6 @@ struct roam_ctrl_cmd { · 6 unmodified lines
1652 union {1642 union {
1653 u8 bssid[ETH_ALEN]; /* WMI_FORCE_ROAM */1643 u8 bssid[ETH_ALEN]; /* WMI_FORCE_ROAM */
1654 u8 roam_mode; /* WMI_SET_ROAM_MODE */1644 u8 roam_mode; /* WMI_SET_ROAM_MODE */
1655 struct bss_bias_info bss; /* WMI_SET_HOST_BIAS */
1656 struct low_rssi_scan_params params; /* WMI_SET_LRSSI_SCAN_PARAMS1645 struct low_rssi_scan_params params; /* WMI_SET_LRSSI_SCAN_PARAMS
1657 */1646 */
1658 } __packed info;1647 } __packed info;
drivers/net/wireless/ath/ath9k/hif_usb.c+0−4
@@ -1382,8 +1382,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, · 1381 unmodified lines
1382 goto err_alloc;1382 goto err_alloc;
1383 }1383 }
1384 1384
1385 usb_get_dev(udev);
1386
1387 hif_dev->udev = udev;1385 hif_dev->udev = udev;
1388 hif_dev->interface = interface;1386 hif_dev->interface = interface;
1389 hif_dev->usb_device_id = id;1387 hif_dev->usb_device_id = id;
@@ -1403,7 +1401,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, · 13 unmodified lines
1403err_fw_req:1401err_fw_req:
1404 usb_set_intfdata(interface, NULL);1402 usb_set_intfdata(interface, NULL);
1405 kfree(hif_dev);1403 kfree(hif_dev);
1406 usb_put_dev(udev);
1407err_alloc:1404err_alloc:
1408 return ret;1405 return ret;
1409}1406}
@@ -1451,7 +1448,6 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) · 41 unmodified lines
1451 1448
1452 kfree(hif_dev);1449 kfree(hif_dev);
1453 dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");1450 dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");
1454 usb_put_dev(udev);
1455}1451}
1456 1452
1457#ifdef CONFIG_PM1453#ifdef CONFIG_PM
drivers/net/wireless/broadcom/b43/dma.c+8−10
@@ -837,18 +837,19 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, · 836 unmodified lines
837 struct b43_dmaring *ring;837 struct b43_dmaring *ring;
838 int i, err;838 int i, err;
839 dma_addr_t dma_test;839 dma_addr_t dma_test;
840 size_t nr_slots;
840 841
841 ring = kzalloc_obj(*ring);842 if (for_tx)
843 nr_slots = B43_TXRING_SLOTS;
844 else
845 nr_slots = B43_RXRING_SLOTS;
846
847 ring = kzalloc_flex(*ring, meta, nr_slots);
842 if (!ring)848 if (!ring)
843 goto out;849 goto out;
844 850
845 ring->nr_slots = B43_RXRING_SLOTS;851 ring->nr_slots = nr_slots;
846 if (for_tx)
847 ring->nr_slots = B43_TXRING_SLOTS;
848 852
849 ring->meta = kzalloc_objs(struct b43_dmadesc_meta, ring->nr_slots);
850 if (!ring->meta)
851 goto err_kfree_ring;
852 for (i = 0; i < ring->nr_slots; i++)853 for (i = 0; i < ring->nr_slots; i++)
853 ring->meta->skb = B43_DMA_PTR_POISON;854 ring->meta->skb = B43_DMA_PTR_POISON;
854 855
@@ -943,8 +944,6 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, · 88 unmodified lines
943 err_kfree_txhdr_cache:944 err_kfree_txhdr_cache:
944 kfree(ring->txhdr_cache);945 kfree(ring->txhdr_cache);
945 err_kfree_meta:946 err_kfree_meta:
946 kfree(ring->meta);
947 err_kfree_ring:
948 kfree(ring);947 kfree(ring);
949 ring = NULL;948 ring = NULL;
950 goto out;949 goto out;
@@ -1004,7 +1003,6 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring, · 53 unmodified lines
1004 free_ringmemory(ring);1003 free_ringmemory(ring);
1005 1004
1006 kfree(ring->txhdr_cache);1005 kfree(ring->txhdr_cache);
1007 kfree(ring->meta);
1008 kfree(ring);1006 kfree(ring);
1009}1007}
1010 1008
drivers/net/wireless/broadcom/b43/dma.h+2−2
@@ -228,8 +228,6 @@ struct b43_dmaring { · 227 unmodified lines
228 const struct b43_dma_ops *ops;228 const struct b43_dma_ops *ops;
229 /* Kernel virtual base address of the ring memory. */229 /* Kernel virtual base address of the ring memory. */
230 void *descbase;230 void *descbase;
231 /* Meta data about all descriptors. */
232 struct b43_dmadesc_meta *meta;
233 /* Cache of TX headers for each TX frame.231 /* Cache of TX headers for each TX frame.
234 * This is to avoid an allocation on each TX.232 * This is to avoid an allocation on each TX.
235 * This is NULL for an RX ring.233 * This is NULL for an RX ring.
@@ -273,6 +271,8 @@ struct b43_dmaring { · 37 unmodified lines
273 /* Statistics: Total number of TX plus all retries. */271 /* Statistics: Total number of TX plus all retries. */
274 u64 nr_total_packet_tries;272 u64 nr_total_packet_tries;
275#endif /* CONFIG_B43_DEBUG */273#endif /* CONFIG_B43_DEBUG */
274 /* Meta data about all descriptors. */
275 struct b43_dmadesc_meta meta[] __counted_by(nr_slots);
276};276};
277 277
278static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset)278static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset)
drivers/net/wireless/intel/iwlwifi/cfg/bz.c+1−1
@@ -10,7 +10,7 @@ · 9 unmodified lines
10#include "fw/api/txq.h"10#include "fw/api/txq.h"
11 11
12/* Highest firmware core release supported */12/* Highest firmware core release supported */
13#define IWL_BZ_UCODE_CORE_MAX 10113#define IWL_BZ_UCODE_CORE_MAX 102
14 14
15/* Lowest firmware API version supported */15/* Lowest firmware API version supported */
16#define IWL_BZ_UCODE_API_MIN 10016#define IWL_BZ_UCODE_API_MIN 100
drivers/net/wireless/intel/iwlwifi/cfg/dr.c+1−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
9#include "fw/api/txq.h"9#include "fw/api/txq.h"
10 10
11/* Highest firmware core release supported */11/* Highest firmware core release supported */
12#define IWL_DR_UCODE_CORE_MAX 10112#define IWL_DR_UCODE_CORE_MAX 102
13 13
14/* Lowest firmware API version supported */14/* Lowest firmware API version supported */
15#define IWL_DR_UCODE_API_MIN 10015#define IWL_DR_UCODE_API_MIN 100
drivers/net/wireless/intel/iwlwifi/cfg/sc.c+1−1
@@ -10,7 +10,7 @@ · 9 unmodified lines
10#include "fw/api/txq.h"10#include "fw/api/txq.h"
11 11
12/* Highest firmware core release supported */12/* Highest firmware core release supported */
13#define IWL_SC_UCODE_CORE_MAX 10113#define IWL_SC_UCODE_CORE_MAX 102
14 14
15/* Lowest firmware API version supported */15/* Lowest firmware API version supported */
16#define IWL_SC_UCODE_API_MIN 10016#define IWL_SC_UCODE_API_MIN 100
drivers/net/wireless/intel/iwlwifi/fw/acpi.c+117−15
@@ -504,7 +504,8 @@ iwl_acpi_parse_chains_table(union acpi_object *table, · 503 unmodified lines
504 u8 num_chains, u8 num_sub_bands)504 u8 num_chains, u8 num_sub_bands)
505{505{
506 for (u8 chain = 0; chain < num_chains; chain++) {506 for (u8 chain = 0; chain < num_chains; chain++) {
507 for (u8 subband = 0; subband < BIOS_SAR_MAX_SUB_BANDS_NUM;507 for (u8 subband = 0;
508 subband < ARRAY_SIZE(chains[chain].subbands);
508 subband++) {509 subband++) {
509 /* if we don't have the values, use the default */510 /* if we don't have the values, use the default */
510 if (subband >= num_sub_bands) {511 if (subband >= num_sub_bands) {
@@ -534,7 +535,23 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt) · 23 unmodified lines
534 if (IS_ERR(data))535 if (IS_ERR(data))
535 return PTR_ERR(data);536 return PTR_ERR(data);
536 537
537 /* start by trying to read revision 2 */538 /* start by trying to read revision 3 */
539 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
540 ACPI_WRDS_WIFI_DATA_SIZE_REV3,
541 &tbl_rev);
542 if (!IS_ERR(wifi_pkg)) {
543 if (tbl_rev != 3) {
544 ret = -EINVAL;
545 goto out_free;
546 }
547
548 num_chains = ACPI_SAR_NUM_CHAINS_REV2;
549 num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV3;
550
551 goto read_table;
552 }
553
554 /* then try revision 2 */
538 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,555 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
539 ACPI_WRDS_WIFI_DATA_SIZE_REV2,556 ACPI_WRDS_WIFI_DATA_SIZE_REV2,
540 &tbl_rev);557 &tbl_rev);
@@ -591,6 +608,13 @@ read_table: · 50 unmodified lines
591 goto out_free;608 goto out_free;
592 }609 }
593 610
611 if (WARN_ON(num_chains * num_sub_bands >
612 ARRAY_SIZE(fwrt->sar_profiles[0].chains) *
613 ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) {
614 ret = -EINVAL;
615 goto out_free;
616 }
617
594 IWL_DEBUG_RADIO(fwrt, "Reading WRDS tbl_rev=%d\n", tbl_rev);618 IWL_DEBUG_RADIO(fwrt, "Reading WRDS tbl_rev=%d\n", tbl_rev);
595 619
596 flags = wifi_pkg->package.elements[1].integer.value;620 flags = wifi_pkg->package.elements[1].integer.value;
@@ -624,7 +648,22 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt) · 27 unmodified lines
624 if (IS_ERR(data))648 if (IS_ERR(data))
625 return PTR_ERR(data);649 return PTR_ERR(data);
626 650
627 /* start by trying to read revision 2 */651 /* start by trying to read revision 3 */
652 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
653 ACPI_EWRD_WIFI_DATA_SIZE_REV3,
654 &tbl_rev);
655 if (!IS_ERR(wifi_pkg)) {
656 if (tbl_rev != 3) {
657 ret = -EINVAL;
658 goto out_free;
659 }
660
661 num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV3;
662
663 goto read_table;
664 }
665
666 /* then try revision 2 */
628 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,667 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
629 ACPI_EWRD_WIFI_DATA_SIZE_REV2,668 ACPI_EWRD_WIFI_DATA_SIZE_REV2,
630 &tbl_rev);669 &tbl_rev);
@@ -679,6 +718,13 @@ read_table: · 48 unmodified lines
679 goto out_free;718 goto out_free;
680 }719 }
681 720
721 if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands >
722 ARRAY_SIZE(fwrt->sar_profiles[0].chains) *
723 ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) {
724 ret = -EINVAL;
725 goto out_free;
726 }
727
682 enabled = !!(wifi_pkg->package.elements[1].integer.value);728 enabled = !!(wifi_pkg->package.elements[1].integer.value);
683 n_profiles = wifi_pkg->package.elements[2].integer.value;729 n_profiles = wifi_pkg->package.elements[2].integer.value;
684 730
@@ -721,6 +767,13 @@ read_table: · 36 unmodified lines
721 if (tbl_rev < 2)767 if (tbl_rev < 2)
722 goto set_enabled;768 goto set_enabled;
723 769
770 if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * 2 * num_sub_bands >
771 ARRAY_SIZE(fwrt->sar_profiles[0].chains) *
772 ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) {
773 ret = -EINVAL;
774 goto out_free;
775 }
776
724 /* parse cdb chains for all profiles */777 /* parse cdb chains for all profiles */
725 for (i = 0; i < n_profiles; i++) {778 for (i = 0; i < n_profiles; i++) {
726 struct iwl_sar_profile_chain *chains;779 struct iwl_sar_profile_chain *chains;
@@ -759,6 +812,12 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt) · 32 unmodified lines
759 u8 profiles;812 u8 profiles;
760 u8 min_profiles;813 u8 min_profiles;
761 } rev_data[] = {814 } rev_data[] = {
815 {
816 .revisions = BIT(4),
817 .bands = ACPI_GEO_NUM_BANDS_REV4,
818 .profiles = ACPI_NUM_GEO_PROFILES_REV3,
819 .min_profiles = BIOS_GEO_MIN_PROFILE_NUM,
820 },
762 {821 {
763 .revisions = BIT(3),822 .revisions = BIT(3),
764 .bands = ACPI_GEO_NUM_BANDS_REV2,823 .bands = ACPI_GEO_NUM_BANDS_REV2,
@@ -812,6 +871,18 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt) · 47 unmodified lines
812 num_bands = rev_data[idx].bands;871 num_bands = rev_data[idx].bands;
813 num_profiles = rev_data[idx].profiles;872 num_profiles = rev_data[idx].profiles;
814 873
874 if (WARN_ON(num_profiles >
875 ARRAY_SIZE(fwrt->geo_profiles))) {
876 ret = -EINVAL;
877 goto out_free;
878 }
879
880 if (WARN_ON(num_bands >
881 ARRAY_SIZE(fwrt->geo_profiles[0].bands))) {
882 ret = -EINVAL;
883 goto out_free;
884 }
885
815 if (rev_data[idx].min_profiles) {886 if (rev_data[idx].min_profiles) {
816 /* read header that says # of profiles */887 /* read header that says # of profiles */
817 union acpi_object *entry;888 union acpi_object *entry;
@@ -851,18 +922,20 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt) · 33 unmodified lines
851 922
852read_table:923read_table:
853 fwrt->geo_rev = tbl_rev;924 fwrt->geo_rev = tbl_rev;
925
854 for (i = 0; i < num_profiles; i++) {926 for (i = 0; i < num_profiles; i++) {
855 for (j = 0; j < BIOS_GEO_MAX_NUM_BANDS; j++) {927 struct iwl_geo_profile *prof = &fwrt->geo_profiles[i];
928
929 for (j = 0; j < ARRAY_SIZE(prof->bands); j++) {
856 union acpi_object *entry;930 union acpi_object *entry;
857 931
858 /*932 /*
859 * num_bands is either 2 or 3, if it's only 2 then933 * num_bands is either 2 or 3 or 4, if it's lower
860 * fill the third band (6 GHz) with the values from934 * than 4, fill the third band (6 GHz) with the values
861 * 5 GHz (second band)935 * from 5 GHz (second band)
862 */936 */
863 if (j >= num_bands) {937 if (j >= num_bands) {
864 fwrt->geo_profiles[i].bands[j].max =938 prof->bands[j].max = prof->bands[1].max;
865 fwrt->geo_profiles[i].bands[1].max;
866 } else {939 } else {
867 entry = &wifi_pkg->package.elements[entry_idx];940 entry = &wifi_pkg->package.elements[entry_idx];
868 entry_idx++;941 entry_idx++;
@@ -872,15 +945,17 @@ read_table: · 3 unmodified lines
872 goto out_free;945 goto out_free;
873 }946 }
874 947
875 fwrt->geo_profiles[i].bands[j].max =948 prof->bands[j].max =
876 entry->integer.value;949 entry->integer.value;
877 }950 }
878 951
879 for (k = 0; k < BIOS_GEO_NUM_CHAINS; k++) {952 for (k = 0;
953 k < ARRAY_SIZE(prof->bands[0].chains);
954 k++) {
880 /* same here as above */955 /* same here as above */
881 if (j >= num_bands) {956 if (j >= num_bands) {
882 fwrt->geo_profiles[i].bands[j].chains[k] =957 prof->bands[j].chains[k] =
883 fwrt->geo_profiles[i].bands[1].chains[k];958 prof->bands[1].chains[k];
884 } else {959 } else {
885 entry = &wifi_pkg->package.elements[entry_idx];960 entry = &wifi_pkg->package.elements[entry_idx];
886 entry_idx++;961 entry_idx++;
@@ -890,7 +965,7 @@ read_table: · 3 unmodified lines
890 goto out_free;965 goto out_free;
891 }966 }
892 967
893 fwrt->geo_profiles[i].bands[j].chains[k] =968 prof->bands[j].chains[k] =
894 entry->integer.value;969 entry->integer.value;
895 }970 }
896 }971 }
@@ -898,6 +973,7 @@ read_table: · 1 unmodified line
898 }973 }
899 974
900 fwrt->geo_num_profiles = num_profiles;975 fwrt->geo_num_profiles = num_profiles;
976 fwrt->geo_bios_source = BIOS_SOURCE_ACPI;
901 fwrt->geo_enabled = true;977 fwrt->geo_enabled = true;
902 ret = 0;978 ret = 0;
903out_free:979out_free:
@@ -915,6 +991,22 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt) · 11 unmodified lines
915 if (IS_ERR(data))991 if (IS_ERR(data))
916 return PTR_ERR(data);992 return PTR_ERR(data);
917 993
994 /* try to read ppag table rev 5 */
995 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
996 ACPI_PPAG_WIFI_DATA_SIZE_V3, &tbl_rev);
997 if (!IS_ERR(wifi_pkg)) {
998 if (tbl_rev == 5) {
999 num_sub_bands = IWL_NUM_SUB_BANDS_V3;
1000 IWL_DEBUG_RADIO(fwrt,
1001 "Reading PPAG table (tbl_rev=%d)\n",
1002 tbl_rev);
1003 goto read_table;
1004 } else {
1005 ret = -EINVAL;
1006 goto out_free;
1007 }
1008 }
1009
918 /* try to read ppag table rev 1 to 4 (all have the same data size) */1010 /* try to read ppag table rev 1 to 4 (all have the same data size) */
919 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,1011 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
920 ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);1012 ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
@@ -950,6 +1042,15 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt) · 29 unmodified lines
950 goto out_free;1042 goto out_free;
951 1043
952read_table:1044read_table:
1045 if (WARN_ON_ONCE(num_sub_bands >
1046 ARRAY_SIZE(fwrt->ppag_chains[0].subbands))) {
1047 ret = -EINVAL;
1048 goto out_free;
1049 }
1050
1051 BUILD_BUG_ON(ACPI_PPAG_NUM_CHAINS >
1052 ARRAY_SIZE(fwrt->ppag_chains));
1053
953 fwrt->ppag_bios_rev = tbl_rev;1054 fwrt->ppag_bios_rev = tbl_rev;
954 flags = &wifi_pkg->package.elements[1];1055 flags = &wifi_pkg->package.elements[1];
955 1056
@@ -966,7 +1067,7 @@ read_table: · 10 unmodified lines
966 * first sub-band (j=0) corresponds to Low-Band (2.4GHz), and the1067 * first sub-band (j=0) corresponds to Low-Band (2.4GHz), and the
967 * following sub-bands to High-Band (5GHz).1068 * following sub-bands to High-Band (5GHz).
968 */1069 */
969 for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {1070 for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
970 for (j = 0; j < num_sub_bands; j++) {1071 for (j = 0; j < num_sub_bands; j++) {
971 union acpi_object *ent;1072 union acpi_object *ent;
972 1073
@@ -980,6 +1081,7 @@ read_table: · 7 unmodified lines
980 }1081 }
981 }1082 }
982 1083
1084 iwl_bios_print_ppag(fwrt, num_sub_bands);
983 fwrt->ppag_bios_source = BIOS_SOURCE_ACPI;1085 fwrt->ppag_bios_source = BIOS_SOURCE_ACPI;
984 ret = 0;1086 ret = 0;
985 1087
drivers/net/wireless/intel/iwlwifi/fw/acpi.h+19−9
@@ -8,11 +8,6 @@ · 7 unmodified lines
8 8
9#include <linux/acpi.h>9#include <linux/acpi.h>
10#include "fw/regulatory.h"10#include "fw/regulatory.h"
11#include "fw/api/commands.h"
12#include "fw/api/power.h"
13#include "fw/api/phy.h"
14#include "fw/api/nvm-reg.h"
15#include "fw/api/config.h"
16#include "fw/img.h"11#include "fw/img.h"
17#include "iwl-trans.h"12#include "iwl-trans.h"
18 13
@@ -44,6 +39,7 @@ · 25 unmodified lines
44#define ACPI_SAR_NUM_SUB_BANDS_REV0 539#define ACPI_SAR_NUM_SUB_BANDS_REV0 5
45#define ACPI_SAR_NUM_SUB_BANDS_REV1 1140#define ACPI_SAR_NUM_SUB_BANDS_REV1 11
46#define ACPI_SAR_NUM_SUB_BANDS_REV2 1141#define ACPI_SAR_NUM_SUB_BANDS_REV2 11
42#define ACPI_SAR_NUM_SUB_BANDS_REV3 12
47 43
48#define ACPI_WRDS_WIFI_DATA_SIZE_REV0 (ACPI_SAR_NUM_CHAINS_REV0 * \44#define ACPI_WRDS_WIFI_DATA_SIZE_REV0 (ACPI_SAR_NUM_CHAINS_REV0 * \
49 ACPI_SAR_NUM_SUB_BANDS_REV0 + 2)45 ACPI_SAR_NUM_SUB_BANDS_REV0 + 2)
@@ -51,6 +47,8 @@ · 1 unmodified line
51 ACPI_SAR_NUM_SUB_BANDS_REV1 + 2)47 ACPI_SAR_NUM_SUB_BANDS_REV1 + 2)
52#define ACPI_WRDS_WIFI_DATA_SIZE_REV2 (ACPI_SAR_NUM_CHAINS_REV2 * \48#define ACPI_WRDS_WIFI_DATA_SIZE_REV2 (ACPI_SAR_NUM_CHAINS_REV2 * \
53 ACPI_SAR_NUM_SUB_BANDS_REV2 + 2)49 ACPI_SAR_NUM_SUB_BANDS_REV2 + 2)
50#define ACPI_WRDS_WIFI_DATA_SIZE_REV3 (ACPI_SAR_NUM_CHAINS_REV2 * \
51 ACPI_SAR_NUM_SUB_BANDS_REV3 + 2)
54#define ACPI_EWRD_WIFI_DATA_SIZE_REV0 ((ACPI_SAR_PROFILE_NUM - 1) * \52#define ACPI_EWRD_WIFI_DATA_SIZE_REV0 ((ACPI_SAR_PROFILE_NUM - 1) * \
55 ACPI_SAR_NUM_CHAINS_REV0 * \53 ACPI_SAR_NUM_CHAINS_REV0 * \
56 ACPI_SAR_NUM_SUB_BANDS_REV0 + 3)54 ACPI_SAR_NUM_SUB_BANDS_REV0 + 3)
@@ -60,11 +58,15 @@ · 3 unmodified lines
60#define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \58#define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
61 ACPI_SAR_NUM_CHAINS_REV2 * \59 ACPI_SAR_NUM_CHAINS_REV2 * \
62 ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)60 ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)
61#define ACPI_EWRD_WIFI_DATA_SIZE_REV3 ((ACPI_SAR_PROFILE_NUM - 1) * \
62 ACPI_SAR_NUM_CHAINS_REV2 * \
63 ACPI_SAR_NUM_SUB_BANDS_REV3 + 3)
63#define ACPI_WPFC_WIFI_DATA_SIZE 5 /* domain and 4 filter config words */64#define ACPI_WPFC_WIFI_DATA_SIZE 5 /* domain and 4 filter config words */
64 65
65/* revision 0 and 1 are identical, except for the semantics in the FW */66/* revision 0 and 1 are identical, except for the semantics in the FW */
66#define ACPI_GEO_NUM_BANDS_REV0 267#define ACPI_GEO_NUM_BANDS_REV0 2
67#define ACPI_GEO_NUM_BANDS_REV2 368#define ACPI_GEO_NUM_BANDS_REV2 3
69#define ACPI_GEO_NUM_BANDS_REV4 4
68 70
69#define ACPI_WRDD_WIFI_DATA_SIZE 271#define ACPI_WRDD_WIFI_DATA_SIZE 2
70#define ACPI_SPLC_WIFI_DATA_SIZE 272#define ACPI_SPLC_WIFI_DATA_SIZE 2
@@ -96,10 +98,18 @@ · 25 unmodified lines
96 */98 */
97#define ACPI_WTAS_WIFI_DATA_SIZE (3 + IWL_WTAS_BLACK_LIST_MAX)99#define ACPI_WTAS_WIFI_DATA_SIZE (3 + IWL_WTAS_BLACK_LIST_MAX)
98 100
99#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \101#define ACPI_PPAG_NUM_CHAINS 2
100 IWL_NUM_SUB_BANDS_V1) + 2)102#define ACPI_PPAG_NUM_BANDS_V1 5
101#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \103#define ACPI_PPAG_NUM_BANDS_V2 11
102 IWL_NUM_SUB_BANDS_V2) + 2)104#define ACPI_PPAG_NUM_BANDS_V3 12
105#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((ACPI_PPAG_NUM_CHAINS * \
106 ACPI_PPAG_NUM_BANDS_V1) + 2)
107#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((ACPI_PPAG_NUM_CHAINS * \
108 ACPI_PPAG_NUM_BANDS_V2) + 2)
109
110/* used for ACPI PPAG table rev 5 */
111#define ACPI_PPAG_WIFI_DATA_SIZE_V3 ((ACPI_PPAG_NUM_CHAINS * \
112 ACPI_PPAG_NUM_BANDS_V3) + 2)
103 113
104#define IWL_SAR_ENABLE_MSK BIT(0)114#define IWL_SAR_ENABLE_MSK BIT(0)
105#define IWL_REDUCE_POWER_FLAGS_POS 1115#define IWL_REDUCE_POWER_FLAGS_POS 1
drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h+2−1
@@ -56,7 +56,8 @@ enum iwl_data_path_subcmd_ids { · 55 unmodified lines
56 RFH_QUEUE_CONFIG_CMD = 0xD,56 RFH_QUEUE_CONFIG_CMD = 0xD,
57 57
58 /**58 /**
59 * @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd_v459 * @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd_v4 or
60 * &struct iwl_tlc_config_cmd_v5 or &struct iwl_tlc_config_cmd.
60 */61 */
61 TLC_MNG_CONFIG_CMD = 0xF,62 TLC_MNG_CONFIG_CMD = 0xF,
62 63
drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h+156−11
@@ -1,6 +1,6 @@
1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2/*2/*
3 * Copyright (C) 2012-2014, 2018-2019, 2021-2025 Intel Corporation3 * Copyright (C) 2012-2014, 2018-2019, 2021-2026 Intel Corporation
4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
5 * Copyright (C) 2016-2017 Intel Deutschland GmbH5 * Copyright (C) 2016-2017 Intel Deutschland GmbH
6 */6 */
@@ -26,7 +26,7 @@ enum iwl_mac_conf_subcmd_ids { · 19 unmodified lines
26 */26 */
27 MISSED_VAP_NOTIF = 0xFA,27 MISSED_VAP_NOTIF = 0xFA,
28 /**28 /**
29 * @SESSION_PROTECTION_CMD: &struct iwl_mvm_session_prot_cmd29 * @SESSION_PROTECTION_CMD: &struct iwl_session_prot_cmd
30 */30 */
31 SESSION_PROTECTION_CMD = 0x5,31 SESSION_PROTECTION_CMD = 0x5,
32 /**32 /**
@@ -34,7 +34,8 @@ enum iwl_mac_conf_subcmd_ids { · 1 unmodified line
34 */34 */
35 CANCEL_CHANNEL_SWITCH_CMD = 0x6,35 CANCEL_CHANNEL_SWITCH_CMD = 0x6,
36 /**36 /**
37 * @MAC_CONFIG_CMD: &struct iwl_mac_config_cmd37 * @MAC_CONFIG_CMD: &struct iwl_mac_config_cmd_v3 or
38 * &struct iwl_mac_config_cmd
38 */39 */
39 MAC_CONFIG_CMD = 0x8,40 MAC_CONFIG_CMD = 0x8,
40 /**41 /**
@@ -42,7 +43,8 @@ enum iwl_mac_conf_subcmd_ids { · 1 unmodified line
42 */43 */
43 LINK_CONFIG_CMD = 0x9,44 LINK_CONFIG_CMD = 0x9,
44 /**45 /**
45 * @STA_CONFIG_CMD: &struct iwl_sta_cfg_cmd46 * @STA_CONFIG_CMD: &struct iwl_sta_cfg_cmd_v1,
47 * &struct iwl_sta_cfg_cmd_v2, or &struct iwl_sta_cfg_cmd
46 */48 */
47 STA_CONFIG_CMD = 0xA,49 STA_CONFIG_CMD = 0xA,
48 /**50 /**
@@ -356,7 +358,7 @@ struct iwl_mac_wifi_gen_support { · 307 unmodified lines
356} __packed;358} __packed;
357 359
358/**360/**
359 * struct iwl_mac_config_cmd - command structure to configure MAC contexts in361 * struct iwl_mac_config_cmd_v3 - command structure to configure MAC contexts in
360 * MLD API for versions 2 and 3362 * MLD API for versions 2 and 3
361 * ( MAC_CONTEXT_CONFIG_CMD = 0x8 )363 * ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
362 *364 *
@@ -375,7 +377,7 @@ struct iwl_mac_wifi_gen_support { · 12 unmodified lines
375 * @client: client mac data377 * @client: client mac data
376 * @p2p_dev: mac data for p2p device378 * @p2p_dev: mac data for p2p device
377 */379 */
378struct iwl_mac_config_cmd {380struct iwl_mac_config_cmd_v3 {
379 __le32 id_and_color;381 __le32 id_and_color;
380 __le32 action;382 __le32 action;
381 /* MAC_CONTEXT_TYPE_API_E */383 /* MAC_CONTEXT_TYPE_API_E */
@@ -393,7 +395,62 @@ struct iwl_mac_config_cmd { · 11 unmodified lines
393 struct iwl_mac_client_data client;395 struct iwl_mac_client_data client;
394 struct iwl_mac_p2p_dev_data p2p_dev;396 struct iwl_mac_p2p_dev_data p2p_dev;
395 };397 };
396} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2_VER_3 */398} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2, _VER_3 */
399
400/**
401 * struct iwl_mac_nan_data - NAN specific MAC data
402 * @ndi_addrs: extra NDI addresses being used
403 * @ndi_addrs_count: number of extra NDI addresses
404 */
405struct iwl_mac_nan_data {
406 struct {
407 u8 addr[ETH_ALEN];
408 __le16 reserved;
409 } __packed ndi_addrs[2];
410 __le32 ndi_addrs_count;
411} __packed; /* MAC_CONTEXT_CONFIG_NAN_DATA_API_S_VER_1 */
412
413/**
414 * struct iwl_mac_config_cmd - command structure to configure MAC contexts in
415 * MLD API for versions 4
416 * ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
417 *
418 * @id_and_color: ID and color of the MAC
419 * @action: action to perform, see &enum iwl_ctxt_action
420 * @mac_type: one of &enum iwl_mac_types
421 * @local_mld_addr: mld address
422 * @reserved_for_local_mld_addr: reserved
423 * @filter_flags: combination of &enum iwl_mac_config_filter_flags
424 * @wifi_gen_v2: he/eht parameters as in cmd version 2
425 * @wifi_gen: he/eht/uhr parameters as in cmd version 3
426 * @nic_not_ack_enabled: mark that the NIC doesn't support receiving
427 * ACK-enabled AGG, (i.e. both BACK and non-BACK frames in single AGG).
428 * If the NIC is not ACK_ENABLED it may use the EOF-bit in first non-0
429 * len delim to determine if AGG or single.
430 * @client: client mac data
431 * @p2p_dev: mac data for p2p device
432 * @nan: NAN specific data (NAN data interface addresses)
433 */
434struct iwl_mac_config_cmd {
435 __le32 id_and_color;
436 __le32 action;
437 /* MAC_CONTEXT_TYPE_API_E */
438 __le32 mac_type;
439 u8 local_mld_addr[6];
440 __le16 reserved_for_local_mld_addr;
441 __le32 filter_flags;
442 union {
443 struct iwl_mac_wifi_gen_support_v2 wifi_gen_v2;
444 struct iwl_mac_wifi_gen_support wifi_gen;
445 };
446 __le32 nic_not_ack_enabled;
447 /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_3 */
448 union {
449 struct iwl_mac_client_data client;
450 struct iwl_mac_p2p_dev_data p2p_dev;
451 struct iwl_mac_nan_data nan;
452 };
453} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_4 */
397 454
398/**455/**
399 * enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being456 * enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being
@@ -652,6 +709,7 @@ struct iwl_link_config_cmd { · 252 unmodified lines
652 */709 */
653#define IWL_FW_MAX_ACTIVE_LINKS_NUM 2710#define IWL_FW_MAX_ACTIVE_LINKS_NUM 2
654#define IWL_FW_MAX_LINK_ID 3711#define IWL_FW_MAX_LINK_ID 3
712#define IWL_FW_MAX_LINKS IWL_FW_MAX_LINK_ID + 1
655 713
656/**714/**
657 * enum iwl_fw_sta_type - FW station types715 * enum iwl_fw_sta_type - FW station types
@@ -662,6 +720,13 @@ struct iwl_link_config_cmd { · 4 unmodified lines
662 * @STATION_TYPE_MCAST: the station used for BCAST / MCAST in GO. Will be720 * @STATION_TYPE_MCAST: the station used for BCAST / MCAST in GO. Will be
663 * suspended / resumed at the right timing depending on the clients'721 * suspended / resumed at the right timing depending on the clients'
664 * power save state and the DTIM timing722 * power save state and the DTIM timing
723 * @STATION_TYPE_NAN_PEER_NMI: NAN management peer station type. A station
724 * of this type can have any number of links (even none) set in the
725 * link_mask. (Supported since version 3.)
726 * @STATION_TYPE_NAN_PEER_NDI: NAN data peer station type. A station
727 * of this type can have any number of links (even none) set in the
728 * link_mask. (Supported since version 3.)
729 * @STATION_TYPE_MAX: maximum number of FW station types
665 * @STATION_TYPE_AUX: aux sta. In the FW there is no need for a special type730 * @STATION_TYPE_AUX: aux sta. In the FW there is no need for a special type
666 * for the aux sta, so this type is only for driver - internal use.731 * for the aux sta, so this type is only for driver - internal use.
667 */732 */
@@ -669,8 +734,11 @@ enum iwl_fw_sta_type { · 1 unmodified line
669 STATION_TYPE_PEER,734 STATION_TYPE_PEER,
670 STATION_TYPE_BCAST_MGMT,735 STATION_TYPE_BCAST_MGMT,
671 STATION_TYPE_MCAST,736 STATION_TYPE_MCAST,
672 STATION_TYPE_AUX,737 STATION_TYPE_NAN_PEER_NMI,
673}; /* STATION_TYPE_E_VER_1 */738 STATION_TYPE_NAN_PEER_NDI,
739 STATION_TYPE_MAX,
740 STATION_TYPE_AUX = STATION_TYPE_MAX /* this doesn't exist in FW */
741}; /* STATION_TYPE_E_VER_1, _VER_2 */
674 742
675/**743/**
676 * struct iwl_sta_cfg_cmd_v1 - cmd structure to add a peer sta to the uCode's744 * struct iwl_sta_cfg_cmd_v1 - cmd structure to add a peer sta to the uCode's
@@ -729,7 +797,7 @@ struct iwl_sta_cfg_cmd_v1 { · 52 unmodified lines
729} __packed; /* STA_CMD_API_S_VER_1 */797} __packed; /* STA_CMD_API_S_VER_1 */
730 798
731/**799/**
732 * struct iwl_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's800 * struct iwl_sta_cfg_cmd_v2 - cmd structure to add a peer sta to the uCode's
733 * station table801 * station table
734 * ( STA_CONFIG_CMD = 0xA )802 * ( STA_CONFIG_CMD = 0xA )
735 *803 *
@@ -769,7 +837,7 @@ struct iwl_sta_cfg_cmd_v1 { · 33 unmodified lines
769 * @mic_compute_pad_delay: MIC compute time padding837 * @mic_compute_pad_delay: MIC compute time padding
770 * @reserved: Reserved for alignment838 * @reserved: Reserved for alignment
771 */839 */
772struct iwl_sta_cfg_cmd {840struct iwl_sta_cfg_cmd_v2 {
773 __le32 sta_id;841 __le32 sta_id;
774 __le32 link_id;842 __le32 link_id;
775 u8 peer_mld_address[ETH_ALEN];843 u8 peer_mld_address[ETH_ALEN];
@@ -799,6 +867,83 @@ struct iwl_sta_cfg_cmd { · 23 unmodified lines
799 u8 reserved[2];867 u8 reserved[2];
800} __packed; /* STA_CMD_API_S_VER_2 */868} __packed; /* STA_CMD_API_S_VER_2 */
801 869
870/**
871 * struct iwl_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
872 * station table
873 * ( STA_CONFIG_CMD = 0xA )
874 *
875 * @sta_id: index of station in uCode's station table
876 * @link_mask: bitmap of link FW IDs used with this STA
877 * @peer_mld_address: the peers mld address
878 * @reserved_for_peer_mld_address: reserved
879 * @peer_link_address: the address of the link that is used to communicate
880 * with this sta
881 * @reserved_for_peer_link_address: reserved
882 * @station_type: type of this station. See &enum iwl_fw_sta_type
883 * @assoc_id: for GO only
884 * @beamform_flags: beam forming controls
885 * @mfp: indicates whether the STA uses management frame protection or not.
886 * @mimo: indicates whether the sta uses mimo or not
887 * @mimo_protection: indicates whether the sta uses mimo protection or not
888 * @ack_enabled: indicates that the AP supports receiving ACK-
889 * enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
890 * @trig_rnd_alloc: indicates that trigger based random allocation
891 * is enabled according to UORA element existence
892 * @tx_ampdu_spacing: minimum A-MPDU spacing:
893 * 4 - 2us density, 5 - 4us density, 6 - 8us density, 7 - 16us density
894 * @tx_ampdu_max_size: maximum A-MPDU length: 0 - 8K, 1 - 16K, 2 - 32K,
895 * 3 - 64K, 4 - 128K, 5 - 256K, 6 - 512K, 7 - 1024K.
896 * @sp_length: the size of the SP in actual number of frames
897 * @uapsd_acs: 4 LS bits are trigger enabled ACs, 4 MS bits are the deliver
898 * enabled ACs.
899 * @pkt_ext: optional, exists according to PPE-present bit in the HE/EHT-PHY
900 * capa
901 * @htc_flags: which features are supported in HTC
902 * @use_ldpc_x2_cw: Indicates whether to use LDPC with double CW
903 * @use_icf: Indicates whether to use ICF instead of RTS
904 * @dps_pad_time: DPS (Dynamic Power Save) padding delay resolution to ensure
905 * proper timing alignment
906 * @dps_trans_delay: DPS minimal time that takes the peer to return to low power
907 * @dps_enabled: flag indicating whether or not DPS is enabled
908 * @mic_prep_pad_delay: MIC prep time padding
909 * @mic_compute_pad_delay: MIC compute time padding
910 * @nmi_sta_id: for an NDI peer STA, the NMI peer STA ID it relates to
911 * @ndi_local_addr: for an NDI peer STA, the local NDI interface MAC address
912 * @reserved: Reserved for alignment
913 */
914struct iwl_sta_cfg_cmd {
915 __le32 sta_id;
916 __le32 link_mask;
917 u8 peer_mld_address[ETH_ALEN];
918 __le16 reserved_for_peer_mld_address;
919 u8 peer_link_address[ETH_ALEN];
920 __le16 reserved_for_peer_link_address;
921 __le32 station_type;
922 __le32 assoc_id;
923 __le32 beamform_flags;
924 __le32 mfp;
925 __le32 mimo;
926 __le32 mimo_protection;
927 __le32 ack_enabled;
928 __le32 trig_rnd_alloc;
929 __le32 tx_ampdu_spacing;
930 __le32 tx_ampdu_max_size;
931 __le32 sp_length;
932 __le32 uapsd_acs;
933 struct iwl_he_pkt_ext_v2 pkt_ext;
934 __le32 htc_flags;
935 u8 use_ldpc_x2_cw;
936 u8 use_icf;
937 u8 dps_pad_time;
938 u8 dps_trans_delay;
939 u8 dps_enabled;
940 u8 mic_prep_pad_delay;
941 u8 mic_compute_pad_delay;
942 u8 nmi_sta_id;
943 u8 ndi_local_addr[ETH_ALEN];
944 u8 reserved[2];
945} __packed; /* STA_CMD_API_S_VER_3 */
946
802/**947/**
803 * struct iwl_aux_sta_cmd - command for AUX STA configuration948 * struct iwl_aux_sta_cmd - command for AUX STA configuration
804 * ( AUX_STA_CMD = 0xB )949 * ( AUX_STA_CMD = 0xB )
drivers/net/wireless/intel/iwlwifi/fw/api/mac.h+2−4
@@ -57,8 +57,7 @@ enum iwl_mac_protection_flags { · 56 unmodified lines
57 * @FW_MAC_TYPE_P2P_DEVICE: P2P Device57 * @FW_MAC_TYPE_P2P_DEVICE: P2P Device
58 * @FW_MAC_TYPE_P2P_STA: P2P client58 * @FW_MAC_TYPE_P2P_STA: P2P client
59 * @FW_MAC_TYPE_GO: P2P GO59 * @FW_MAC_TYPE_GO: P2P GO
60 * @FW_MAC_TYPE_TEST: ?60 * @FW_MAC_TYPE_NAN: NAN (since version 4)
61 * @FW_MAC_TYPE_MAX: highest support MAC type
62 */61 */
63enum iwl_mac_types {62enum iwl_mac_types {
64 FW_MAC_TYPE_FIRST = 1,63 FW_MAC_TYPE_FIRST = 1,
@@ -70,8 +69,7 @@ enum iwl_mac_types { · 5 unmodified lines
70 FW_MAC_TYPE_P2P_DEVICE,69 FW_MAC_TYPE_P2P_DEVICE,
71 FW_MAC_TYPE_P2P_STA,70 FW_MAC_TYPE_P2P_STA,
72 FW_MAC_TYPE_GO,71 FW_MAC_TYPE_GO,
73 FW_MAC_TYPE_TEST,72 FW_MAC_TYPE_NAN,
74 FW_MAC_TYPE_MAX = FW_MAC_TYPE_TEST
75}; /* MAC_CONTEXT_TYPE_API_E_VER_1 */73}; /* MAC_CONTEXT_TYPE_API_E_VER_1 */
76 74
77/**75/**
drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h+14−4
@@ -204,7 +204,7 @@ struct iwl_nvm_get_info_phy { · 203 unmodified lines
204} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */204} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
205 205
206#define IWL_NUM_CHANNELS_V1 51206#define IWL_NUM_CHANNELS_V1 51
207#define IWL_NUM_CHANNELS 110207#define IWL_NUM_CHANNELS_V2 110
208 208
209/**209/**
210 * struct iwl_nvm_get_info_regulatory_v1 - regulatory information210 * struct iwl_nvm_get_info_regulatory_v1 - regulatory information
@@ -227,7 +227,7 @@ struct iwl_nvm_get_info_regulatory_v1 { · 16 unmodified lines
227struct iwl_nvm_get_info_regulatory {227struct iwl_nvm_get_info_regulatory {
228 __le32 lar_enabled;228 __le32 lar_enabled;
229 __le32 n_channels;229 __le32 n_channels;
230 __le32 channel_profile[IWL_NUM_CHANNELS];230 __le32 channel_profile[IWL_NUM_CHANNELS_V2];
231} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */231} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */
232 232
233/**233/**
@@ -701,13 +701,23 @@ struct iwl_pnvm_init_complete_ntfy { · 467 unmodified lines
701#define UATS_TABLE_COL_SIZE 13701#define UATS_TABLE_COL_SIZE 13
702 702
703/**703/**
704 * struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD704 * struct iwl_mcc_allowed_ap_type_cmd_v1 - struct for MCC_ALLOWED_AP_TYPE_CMD
705 * @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS)705 * @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS)
706 * @reserved: reserved706 * @reserved: reserved
707 */707 */
708struct iwl_mcc_allowed_ap_type_cmd {708struct iwl_mcc_allowed_ap_type_cmd_v1 {
709 u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];709 u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
710 __le16 reserved;710 __le16 reserved;
711} __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_1 */711} __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_1 */
712 712
713/**
714 * struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD
715 * @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS)
716 * @mcc_to_ap_type_unii9_map: mapping an MCC to UNII-9 AP type support allowed
717 */
718struct iwl_mcc_allowed_ap_type_cmd {
719 u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
720 u8 mcc_to_ap_type_unii9_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
721} __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_2 */
722
713#endif /* __iwl_fw_api_nvm_reg_h__ */723#endif /* __iwl_fw_api_nvm_reg_h__ */
drivers/net/wireless/intel/iwlwifi/fw/api/power.h+36−1
@@ -269,6 +269,7 @@ enum iwl_dev_tx_power_cmd_mode { · 268 unmodified lines
269#define IWL_NUM_CHAIN_LIMITS 2269#define IWL_NUM_CHAIN_LIMITS 2
270#define IWL_NUM_SUB_BANDS_V1 5270#define IWL_NUM_SUB_BANDS_V1 5
271#define IWL_NUM_SUB_BANDS_V2 11271#define IWL_NUM_SUB_BANDS_V2 11
272#define IWL_NUM_SUB_BANDS_V3 12
272 273
273/**274/**
274 * struct iwl_dev_tx_power_common - Common part of the TX power reduction cmd275 * struct iwl_dev_tx_power_common - Common part of the TX power reduction cmd
@@ -425,24 +426,38 @@ struct iwl_dev_tx_power_cmd_v10 { · 150 unmodified lines
425 __le32 flags;426 __le32 flags;
426} __packed; /* TX_REDUCED_POWER_API_S_VER_10 */427} __packed; /* TX_REDUCED_POWER_API_S_VER_10 */
427 428
429struct iwl_dev_tx_power_cmd_v11 {
430 __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];
431 u8 per_chain_restriction_changed;
432 u8 reserved;
433 __le32 timer_period;
434 __le32 flags;
435} __packed; /* TX_REDUCED_POWER_API_S_VER_11 */
436
428/*437/*
429 * struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)438 * struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
430 * @common: common part of the command439 * @common: common part of the command
431 * @v9: version 9 part of the command440 * @v9: version 9 part of the command
432 * @v10: version 10 part of the command441 * @v10: version 10 part of the command
442 * @v11: version 11 part of the command
433 */443 */
434struct iwl_dev_tx_power_cmd {444struct iwl_dev_tx_power_cmd {
435 struct iwl_dev_tx_power_common common;445 struct iwl_dev_tx_power_common common;
436 union {446 union {
437 struct iwl_dev_tx_power_cmd_v9 v9;447 struct iwl_dev_tx_power_cmd_v9 v9;
438 struct iwl_dev_tx_power_cmd_v10 v10;448 struct iwl_dev_tx_power_cmd_v10 v10;
449 struct iwl_dev_tx_power_cmd_v11 v11;
439 };450 };
440} __packed; /* TX_REDUCED_POWER_API_S_VER_9_VER10 */451} __packed; /* TX_REDUCED_POWER_API_S_VER_9
452 * TX_REDUCED_POWER_API_S_VER_10
453 * TX_REDUCED_POWER_API_S_VER_11
454 */
441 455
442#define IWL_NUM_GEO_PROFILES 3456#define IWL_NUM_GEO_PROFILES 3
443#define IWL_NUM_GEO_PROFILES_V3 8457#define IWL_NUM_GEO_PROFILES_V3 8
444#define IWL_NUM_BANDS_PER_CHAIN_V1 2458#define IWL_NUM_BANDS_PER_CHAIN_V1 2
445#define IWL_NUM_BANDS_PER_CHAIN_V2 3459#define IWL_NUM_BANDS_PER_CHAIN_V2 3
460#define IWL_NUM_BANDS_PER_CHAIN_V6 4
446 461
447/**462/**
448 * enum iwl_geo_per_chain_offset_operation - type of operation463 * enum iwl_geo_per_chain_offset_operation - type of operation
@@ -524,12 +539,25 @@ struct iwl_geo_tx_power_profiles_cmd_v5 { · 75 unmodified lines
524 __le32 table_revision;539 __le32 table_revision;
525} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */540} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */
526 541
542/**
543 * struct iwl_geo_tx_power_profiles_cmd_v6 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
544 * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
545 * @table: offset profile per band.
546 * @bios_hdr: describes the revision and the source of the BIOS
547 */
548struct iwl_geo_tx_power_profiles_cmd_v6 {
549 __le32 ops;
550 struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V6];
551 struct iwl_bios_config_hdr bios_hdr;
552} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_6 */
553
527union iwl_geo_tx_power_profiles_cmd {554union iwl_geo_tx_power_profiles_cmd {
528 struct iwl_geo_tx_power_profiles_cmd_v1 v1;555 struct iwl_geo_tx_power_profiles_cmd_v1 v1;
529 struct iwl_geo_tx_power_profiles_cmd_v2 v2;556 struct iwl_geo_tx_power_profiles_cmd_v2 v2;
530 struct iwl_geo_tx_power_profiles_cmd_v3 v3;557 struct iwl_geo_tx_power_profiles_cmd_v3 v3;
531 struct iwl_geo_tx_power_profiles_cmd_v4 v4;558 struct iwl_geo_tx_power_profiles_cmd_v4 v4;
532 struct iwl_geo_tx_power_profiles_cmd_v5 v5;559 struct iwl_geo_tx_power_profiles_cmd_v5 v5;
560 struct iwl_geo_tx_power_profiles_cmd_v6 v6;
533};561};
534 562
535/**563/**
@@ -573,6 +601,7 @@ enum iwl_ppag_flags { · 37 unmodified lines
573 * @v1: command version 1 structure.601 * @v1: command version 1 structure.
574 * @v5: command version 5 structure.602 * @v5: command version 5 structure.
575 * @v7: command version 7 structure.603 * @v7: command version 7 structure.
604 * @v8: command version 8 structure.
576 * @v1.flags: values from &enum iwl_ppag_flags605 * @v1.flags: values from &enum iwl_ppag_flags
577 * @v1.gain: table of antenna gain values per chain and sub-band606 * @v1.gain: table of antenna gain values per chain and sub-band
578 * @v1.reserved: reserved607 * @v1.reserved: reserved
@@ -581,6 +610,8 @@ enum iwl_ppag_flags { · 2 unmodified lines
581 * @v7.ppag_config_info: see @struct bios_value_u32610 * @v7.ppag_config_info: see @struct bios_value_u32
582 * @v7.gain: table of antenna gain values per chain and sub-band611 * @v7.gain: table of antenna gain values per chain and sub-band
583 * @v7.reserved: reserved612 * @v7.reserved: reserved
613 * @v8.ppag_config_info: see @struct bios_value_u32
614 * @v8.gain: table of antenna gain values per chain and sub-band
584 */615 */
585union iwl_ppag_table_cmd {616union iwl_ppag_table_cmd {
586 struct {617 struct {
@@ -598,6 +629,10 @@ union iwl_ppag_table_cmd { · 11 unmodified lines
598 s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];629 s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
599 s8 reserved[2];630 s8 reserved[2];
600 } __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */631 } __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */
632 struct {
633 struct bios_value_u32 ppag_config_info;
634 s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];
635 } __packed v8; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_8 */
601} __packed;636} __packed;
602 637
603#define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)638#define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
drivers/net/wireless/intel/iwlwifi/fw/api/scan.h+45−0
@@ -985,6 +985,7 @@ struct iwl_scan_probe_params_v4 { · 984 unmodified lines
985} __packed; /* SCAN_PROBE_PARAMS_API_S_VER_4 */985} __packed; /* SCAN_PROBE_PARAMS_API_S_VER_4 */
986 986
987#define SCAN_MAX_NUM_CHANS_V3 67987#define SCAN_MAX_NUM_CHANS_V3 67
988#define SCAN_MAX_NUM_CHANS_V4 68
988 989
989/**990/**
990 * struct iwl_scan_channel_params_v4 - channel params991 * struct iwl_scan_channel_params_v4 - channel params
@@ -1027,6 +1028,24 @@ struct iwl_scan_channel_params_v7 { · 36 unmodified lines
1027 struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V3];1028 struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V3];
1028} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */1029} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */
1029 1030
1031/**
1032 * struct iwl_scan_channel_params_v8 - channel params
1033 * @flags: channel flags &enum iwl_scan_channel_flags
1034 * @count: num of channels in scan request
1035 * @n_aps_override: override the number of APs the FW uses to calculate dwell
1036 * time when adaptive dwell is used.
1037 * Channel k will use n_aps_override[i] when BIT(20 + i) is set in
1038 * channel_config[k].flags
1039 * @channel_config: array of explicit channel configurations
1040 * for 2.4Ghz and 5.2Ghz bands
1041 */
1042struct iwl_scan_channel_params_v8 {
1043 u8 flags;
1044 u8 count;
1045 u8 n_aps_override[2];
1046 struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V4];
1047} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_8 */
1048
1030/**1049/**
1031 * struct iwl_scan_general_params_v11 - channel params1050 * struct iwl_scan_general_params_v11 - channel params
1032 * @flags: &enum iwl_umac_scan_general_flags_v21051 * @flags: &enum iwl_umac_scan_general_flags_v2
@@ -1109,6 +1128,20 @@ struct iwl_scan_req_params_v17 { · 76 unmodified lines
1109 struct iwl_scan_probe_params_v4 probe_params;1128 struct iwl_scan_probe_params_v4 probe_params;
1110} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */1129} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */
1111 1130
1131/**
1132 * struct iwl_scan_req_params_v18 - scan request parameters (v18)
1133 * @general_params: &struct iwl_scan_general_params_v11
1134 * @channel_params: &struct iwl_scan_channel_params_v8
1135 * @periodic_params: &struct iwl_scan_periodic_parms_v1
1136 * @probe_params: &struct iwl_scan_probe_params_v4
1137 */
1138struct iwl_scan_req_params_v18 {
1139 struct iwl_scan_general_params_v11 general_params;
1140 struct iwl_scan_channel_params_v8 channel_params;
1141 struct iwl_scan_periodic_parms_v1 periodic_params;
1142 struct iwl_scan_probe_params_v4 probe_params;
1143} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_18 */
1144
1112/**1145/**
1113 * struct iwl_scan_req_umac_v12 - scan request command (v12)1146 * struct iwl_scan_req_umac_v12 - scan request command (v12)
1114 * @uid: scan id, &enum iwl_umac_scan_uid_offsets1147 * @uid: scan id, &enum iwl_umac_scan_uid_offsets
@@ -1133,6 +1166,18 @@ struct iwl_scan_req_umac_v17 { · 18 unmodified lines
1133 struct iwl_scan_req_params_v17 scan_params;1166 struct iwl_scan_req_params_v17 scan_params;
1134} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */1167} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */
1135 1168
1169/**
1170 * struct iwl_scan_req_umac_v18 - scan request command (v18)
1171 * @uid: scan id, &enum iwl_umac_scan_uid_offsets
1172 * @ooc_priority: out of channel priority - &enum iwl_scan_priority
1173 * @scan_params: scan parameters
1174 */
1175struct iwl_scan_req_umac_v18 {
1176 __le32 uid;
1177 __le32 ooc_priority;
1178 struct iwl_scan_req_params_v18 scan_params;
1179} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_18 */
1180
1136/**1181/**
1137 * struct iwl_umac_scan_abort - scan abort command1182 * struct iwl_umac_scan_abort - scan abort command
1138 * @uid: scan id, &enum iwl_umac_scan_uid_offsets1183 * @uid: scan id, &enum iwl_umac_scan_uid_offsets
drivers/net/wireless/intel/iwlwifi/fw/api/stats.h+2−3
@@ -598,7 +598,6 @@ struct iwl_stats_ntfy_per_sta { · 597 unmodified lines
598} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */598} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */
599 599
600#define IWL_STATS_MAX_PHY_OPERATIONAL 3600#define IWL_STATS_MAX_PHY_OPERATIONAL 3
601#define IWL_STATS_MAX_FW_LINKS (IWL_FW_MAX_LINK_ID + 1)
602 601
603/**602/**
604 * struct iwl_system_statistics_notif_oper - statistics notification603 * struct iwl_system_statistics_notif_oper - statistics notification
@@ -610,7 +609,7 @@ struct iwl_stats_ntfy_per_sta { · 5 unmodified lines
610 */609 */
611struct iwl_system_statistics_notif_oper {610struct iwl_system_statistics_notif_oper {
612 __le32 time_stamp;611 __le32 time_stamp;
613 struct iwl_stats_ntfy_per_link per_link[IWL_STATS_MAX_FW_LINKS];612 struct iwl_stats_ntfy_per_link per_link[IWL_FW_MAX_LINKS];
614 struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];613 struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
615 struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];614 struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];
616} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */615} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */
@@ -624,7 +623,7 @@ struct iwl_system_statistics_notif_oper { · 7 unmodified lines
624 */623 */
625struct iwl_system_statistics_part1_notif_oper {624struct iwl_system_statistics_part1_notif_oper {
626 __le32 time_stamp;625 __le32 time_stamp;
627 struct iwl_stats_ntfy_part1_per_link per_link[IWL_STATS_MAX_FW_LINKS];626 struct iwl_stats_ntfy_part1_per_link per_link[IWL_FW_MAX_LINKS];
628 __le32 per_phy_crc_error_stats[IWL_STATS_MAX_PHY_OPERATIONAL];627 __le32 per_phy_crc_error_stats[IWL_STATS_MAX_PHY_OPERATIONAL];
629} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_API_S_VER_4 */628} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_API_S_VER_4 */
630 629
drivers/net/wireless/intel/iwlwifi/fw/dbg.c+2−2
@@ -2933,7 +2933,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, · 2932 unmodified lines
2933 IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",2933 IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",
2934 le32_to_cpu(desc->trig_desc.type));2934 le32_to_cpu(desc->trig_desc.type));
2935 2935
2936 queue_delayed_work(system_unbound_wq, &wk_data->wk,2936 queue_delayed_work(system_dfl_wq, &wk_data->wk,
2937 usecs_to_jiffies(delay));2937 usecs_to_jiffies(delay));
2938 2938
2939 return 0;2939 return 0;
@@ -3236,7 +3236,7 @@ int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, · 296 unmodified lines
3236 if (sync)3236 if (sync)
3237 iwl_fw_dbg_collect_sync(fwrt, idx);3237 iwl_fw_dbg_collect_sync(fwrt, idx);
3238 else3238 else
3239 queue_delayed_work(system_unbound_wq,3239 queue_delayed_work(system_dfl_wq,
3240 &fwrt->dump.wks[idx].wk,3240 &fwrt->dump.wks[idx].wk,
3241 usecs_to_jiffies(delay));3241 usecs_to_jiffies(delay));
3242 3242
drivers/net/wireless/intel/iwlwifi/fw/dump.c+1−68
@@ -1,6 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/*2/*
3 * Copyright (C) 2012-2014, 2018-2025 Intel Corporation3 * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
4 * Copyright (C) 2013-2014 Intel Mobile Communications GmbH4 * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
5 * Copyright (C) 2015-2017 Intel Deutschland GmbH5 * Copyright (C) 2015-2017 Intel Deutschland GmbH
6 */6 */
@@ -128,19 +128,11 @@ static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt) · 121 unmodified lines
128 128
129 IWL_ERR(fwrt, "0x%08X | %s\n", table.error_id,129 IWL_ERR(fwrt, "0x%08X | %s\n", table.error_id,
130 iwl_fw_lookup_assert_desc(table.error_id));130 iwl_fw_lookup_assert_desc(table.error_id));
131 IWL_ERR(fwrt, "0x%08X | umac branchlink1\n", table.blink1);
132 IWL_ERR(fwrt, "0x%08X | umac branchlink2\n", table.blink2);
133 IWL_ERR(fwrt, "0x%08X | umac interruptlink1\n", table.ilink1);
134 IWL_ERR(fwrt, "0x%08X | umac interruptlink2\n", table.ilink2);131 IWL_ERR(fwrt, "0x%08X | umac interruptlink2\n", table.ilink2);
135 IWL_ERR(fwrt, "0x%08X | umac data1\n", table.data1);132 IWL_ERR(fwrt, "0x%08X | umac data1\n", table.data1);
136 IWL_ERR(fwrt, "0x%08X | umac data2\n", table.data2);133 IWL_ERR(fwrt, "0x%08X | umac data2\n", table.data2);
137 IWL_ERR(fwrt, "0x%08X | umac data3\n", table.data3);134 IWL_ERR(fwrt, "0x%08X | umac data3\n", table.data3);
138 IWL_ERR(fwrt, "0x%08X | umac major\n", table.umac_major);
139 IWL_ERR(fwrt, "0x%08X | umac minor\n", table.umac_minor);
140 IWL_ERR(fwrt, "0x%08X | frame pointer\n", table.frame_pointer);
141 IWL_ERR(fwrt, "0x%08X | stack pointer\n", table.stack_pointer);
142 IWL_ERR(fwrt, "0x%08X | last host cmd\n", table.cmd_header);135 IWL_ERR(fwrt, "0x%08X | last host cmd\n", table.cmd_header);
143 IWL_ERR(fwrt, "0x%08X | isr status reg\n", table.nic_isr_pref);
144}136}
145 137
146static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_num)138static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_num)
@@ -200,39 +192,10 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu · 53 unmodified lines
200 192
201 IWL_ERR(fwrt, "0x%08X | %-28s\n", table.error_id,193 IWL_ERR(fwrt, "0x%08X | %-28s\n", table.error_id,
202 iwl_fw_lookup_assert_desc(table.error_id));194 iwl_fw_lookup_assert_desc(table.error_id));
203 IWL_ERR(fwrt, "0x%08X | trm_hw_status0\n", table.trm_hw_status0);
204 IWL_ERR(fwrt, "0x%08X | trm_hw_status1\n", table.trm_hw_status1);
205 IWL_ERR(fwrt, "0x%08X | branchlink2\n", table.blink2);
206 IWL_ERR(fwrt, "0x%08X | interruptlink1\n", table.ilink1);
207 IWL_ERR(fwrt, "0x%08X | interruptlink2\n", table.ilink2);195 IWL_ERR(fwrt, "0x%08X | interruptlink2\n", table.ilink2);
208 IWL_ERR(fwrt, "0x%08X | data1\n", table.data1);196 IWL_ERR(fwrt, "0x%08X | data1\n", table.data1);
209 IWL_ERR(fwrt, "0x%08X | data2\n", table.data2);197 IWL_ERR(fwrt, "0x%08X | data2\n", table.data2);
210 IWL_ERR(fwrt, "0x%08X | data3\n", table.data3);198 IWL_ERR(fwrt, "0x%08X | data3\n", table.data3);
211 IWL_ERR(fwrt, "0x%08X | beacon time\n", table.bcon_time);
212 IWL_ERR(fwrt, "0x%08X | tsf low\n", table.tsf_low);
213 IWL_ERR(fwrt, "0x%08X | tsf hi\n", table.tsf_hi);
214 IWL_ERR(fwrt, "0x%08X | time gp1\n", table.gp1);
215 IWL_ERR(fwrt, "0x%08X | time gp2\n", table.gp2);
216 IWL_ERR(fwrt, "0x%08X | uCode revision type\n", table.fw_rev_type);
217 IWL_ERR(fwrt, "0x%08X | uCode version major\n", table.major);
218 IWL_ERR(fwrt, "0x%08X | uCode version minor\n", table.minor);
219 IWL_ERR(fwrt, "0x%08X | hw version\n", table.hw_ver);
220 IWL_ERR(fwrt, "0x%08X | board version\n", table.brd_ver);
221 IWL_ERR(fwrt, "0x%08X | hcmd\n", table.hcmd);
222 IWL_ERR(fwrt, "0x%08X | isr0\n", table.isr0);
223 IWL_ERR(fwrt, "0x%08X | isr1\n", table.isr1);
224 IWL_ERR(fwrt, "0x%08X | isr2\n", table.isr2);
225 IWL_ERR(fwrt, "0x%08X | isr3\n", table.isr3);
226 IWL_ERR(fwrt, "0x%08X | isr4\n", table.isr4);
227 IWL_ERR(fwrt, "0x%08X | last cmd Id\n", table.last_cmd_id);
228 IWL_ERR(fwrt, "0x%08X | wait_event\n", table.wait_event);
229 IWL_ERR(fwrt, "0x%08X | l2p_control\n", table.l2p_control);
230 IWL_ERR(fwrt, "0x%08X | l2p_duration\n", table.l2p_duration);
231 IWL_ERR(fwrt, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid);
232 IWL_ERR(fwrt, "0x%08X | l2p_addr_match\n", table.l2p_addr_match);
233 IWL_ERR(fwrt, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
234 IWL_ERR(fwrt, "0x%08X | timestamp\n", table.u_timestamp);
235 IWL_ERR(fwrt, "0x%08X | flow_handler\n", table.flow_handler);
236}199}
237 200
238/*201/*
@@ -264,7 +227,6 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt, int idx) · 25 unmodified lines
264 struct iwl_trans *trans = fwrt->trans;227 struct iwl_trans *trans = fwrt->trans;
265 struct iwl_tcm_error_event_table table = {};228 struct iwl_tcm_error_event_table table = {};
266 u32 base = fwrt->trans->dbg.tcm_error_event_table[idx];229 u32 base = fwrt->trans->dbg.tcm_error_event_table[idx];
267 int i;
268 u32 flag = idx ? IWL_ERROR_EVENT_TABLE_TCM2 :230 u32 flag = idx ? IWL_ERROR_EVENT_TABLE_TCM2 :
269 IWL_ERROR_EVENT_TABLE_TCM1;231 IWL_ERROR_EVENT_TABLE_TCM1;
270 232
@@ -275,23 +237,10 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt, int idx) · 4 unmodified lines
275 237
276 IWL_ERR(fwrt, "TCM%d status:\n", idx + 1);238 IWL_ERR(fwrt, "TCM%d status:\n", idx + 1);
277 IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);239 IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
278 IWL_ERR(fwrt, "0x%08X | tcm branchlink2\n", table.blink2);
279 IWL_ERR(fwrt, "0x%08X | tcm interruptlink1\n", table.ilink1);
280 IWL_ERR(fwrt, "0x%08X | tcm interruptlink2\n", table.ilink2);240 IWL_ERR(fwrt, "0x%08X | tcm interruptlink2\n", table.ilink2);
281 IWL_ERR(fwrt, "0x%08X | tcm data1\n", table.data1);241 IWL_ERR(fwrt, "0x%08X | tcm data1\n", table.data1);
282 IWL_ERR(fwrt, "0x%08X | tcm data2\n", table.data2);242 IWL_ERR(fwrt, "0x%08X | tcm data2\n", table.data2);
283 IWL_ERR(fwrt, "0x%08X | tcm data3\n", table.data3);243 IWL_ERR(fwrt, "0x%08X | tcm data3\n", table.data3);
284 IWL_ERR(fwrt, "0x%08X | tcm log PC\n", table.logpc);
285 IWL_ERR(fwrt, "0x%08X | tcm frame pointer\n", table.frame_pointer);
286 IWL_ERR(fwrt, "0x%08X | tcm stack pointer\n", table.stack_pointer);
287 IWL_ERR(fwrt, "0x%08X | tcm msg ID\n", table.msgid);
288 IWL_ERR(fwrt, "0x%08X | tcm ISR status\n", table.isr);
289 for (i = 0; i < ARRAY_SIZE(table.hw_status); i++)
290 IWL_ERR(fwrt, "0x%08X | tcm HW status[%d]\n",
291 table.hw_status[i], i);
292 for (i = 0; i < ARRAY_SIZE(table.sw_status); i++)
293 IWL_ERR(fwrt, "0x%08X | tcm SW status[%d]\n",
294 table.sw_status[i], i);
295}244}
296 245
297/*246/*
@@ -338,26 +287,10 @@ static void iwl_fwrt_dump_rcm_error_log(struct iwl_fw_runtime *fwrt, int idx) · 40 unmodified lines
338 287
339 IWL_ERR(fwrt, "RCM%d status:\n", idx + 1);288 IWL_ERR(fwrt, "RCM%d status:\n", idx + 1);
340 IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);289 IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
341 IWL_ERR(fwrt, "0x%08X | rcm branchlink2\n", table.blink2);
342 IWL_ERR(fwrt, "0x%08X | rcm interruptlink1\n", table.ilink1);
343 IWL_ERR(fwrt, "0x%08X | rcm interruptlink2\n", table.ilink2);290 IWL_ERR(fwrt, "0x%08X | rcm interruptlink2\n", table.ilink2);
344 IWL_ERR(fwrt, "0x%08X | rcm data1\n", table.data1);291 IWL_ERR(fwrt, "0x%08X | rcm data1\n", table.data1);
345 IWL_ERR(fwrt, "0x%08X | rcm data2\n", table.data2);292 IWL_ERR(fwrt, "0x%08X | rcm data2\n", table.data2);
346 IWL_ERR(fwrt, "0x%08X | rcm data3\n", table.data3);293 IWL_ERR(fwrt, "0x%08X | rcm data3\n", table.data3);
347 IWL_ERR(fwrt, "0x%08X | rcm log PC\n", table.logpc);
348 IWL_ERR(fwrt, "0x%08X | rcm frame pointer\n", table.frame_pointer);
349 IWL_ERR(fwrt, "0x%08X | rcm stack pointer\n", table.stack_pointer);
350 IWL_ERR(fwrt, "0x%08X | rcm msg ID\n", table.msgid);
351 IWL_ERR(fwrt, "0x%08X | rcm ISR status\n", table.isr);
352 IWL_ERR(fwrt, "0x%08X | frame HW status\n", table.frame_hw_status);
353 IWL_ERR(fwrt, "0x%08X | LMAC-to-RCM request mbox\n",
354 table.mbx_lmac_to_rcm_req);
355 IWL_ERR(fwrt, "0x%08X | RCM-to-LMAC request mbox\n",
356 table.mbx_rcm_to_lmac_req);
357 IWL_ERR(fwrt, "0x%08X | MAC header control\n", table.mh_ctl);
358 IWL_ERR(fwrt, "0x%08X | MAC header addr1 low\n", table.mh_addr1_lo);
359 IWL_ERR(fwrt, "0x%08X | MAC header info\n", table.mh_info);
360 IWL_ERR(fwrt, "0x%08X | MAC header error\n", table.mh_err);
361}294}
362 295
363static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)296static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
drivers/net/wireless/intel/iwlwifi/fw/file.h+15−0
@@ -103,6 +103,7 @@ enum iwl_ucode_tlv_type { · 102 unmodified lines
103 IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,103 IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
104 IWL_UCODE_TLV_CURRENT_PC = 68,104 IWL_UCODE_TLV_CURRENT_PC = 68,
105 IWL_UCODE_TLV_FSEQ_BIN_VERSION = 72,105 IWL_UCODE_TLV_FSEQ_BIN_VERSION = 72,
106 IWL_UCODE_TLV_CMD_BIOS_TABLE = 73,
106 107
107 /* contains sub-sections like PNVM file does (did) */108 /* contains sub-sections like PNVM file does (did) */
108 IWL_UCODE_TLV_PNVM_DATA = 74,109 IWL_UCODE_TLV_PNVM_DATA = 74,
@@ -1040,6 +1041,20 @@ struct iwl_fw_cmd_version { · 931 unmodified lines
1040 u8 notif_ver;1041 u8 notif_ver;
1041} __packed;1042} __packed;
1042 1043
1044/**
1045 * struct iwl_fw_cmd_bios_table - firmware command BIOS revision entry
1046 * @cmd: command ID
1047 * @group: group ID
1048 * @max_acpi_revision: max supported ACPI revision of command.
1049 * @max_uefi_revision: max supported UEFI revision of command.
1050 */
1051struct iwl_fw_cmd_bios_table {
1052 u8 cmd;
1053 u8 group;
1054 u8 max_acpi_revision;
1055 u8 max_uefi_revision;
1056} __packed;
1057
1043struct iwl_fw_tcm_error_addr {1058struct iwl_fw_tcm_error_addr {
1044 __le32 addr;1059 __le32 addr;
1045}; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */1060}; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */
drivers/net/wireless/intel/iwlwifi/fw/img.c+31−1
@@ -1,11 +1,41 @@
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/*2/*
3 * Copyright(c) 2019 - 2021 Intel Corporation3 * Copyright(c) 2019 - 2021 Intel Corporation
4 * Copyright(c) 2024 Intel Corporation4 * Copyright(c) 2024 - 2025 Intel Corporation
5 */5 */
6#include <fw/api/commands.h>6#include <fw/api/commands.h>
7#include "img.h"7#include "img.h"
8 8
9u8 iwl_fw_lookup_cmd_bios_supported_revision(const struct iwl_fw *fw,
10 enum bios_source table_source,
11 u32 cmd_id, u8 def)
12{
13 const struct iwl_fw_cmd_bios_table *entry;
14 /* prior to LONG_GROUP, we never used this CMD version API */
15 u8 grp = iwl_cmd_groupid(cmd_id) ?: LONG_GROUP;
16 u8 cmd = iwl_cmd_opcode(cmd_id);
17
18 if (table_source != BIOS_SOURCE_ACPI &&
19 table_source != BIOS_SOURCE_UEFI)
20 return def;
21
22 if (!fw->ucode_capa.cmd_bios_tables ||
23 !fw->ucode_capa.n_cmd_bios_tables)
24 return def;
25
26 entry = fw->ucode_capa.cmd_bios_tables;
27 for (int i = 0; i < fw->ucode_capa.n_cmd_bios_tables; i++, entry++) {
28 if (entry->group == grp && entry->cmd == cmd) {
29 if (table_source == BIOS_SOURCE_ACPI)
30 return entry->max_acpi_revision;
31 return entry->max_uefi_revision;
32 }
33 }
34
35 return def;
36}
37EXPORT_SYMBOL_GPL(iwl_fw_lookup_cmd_bios_supported_revision);
38
9u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def)39u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def)
10{40{
11 const struct iwl_fw_cmd_version *entry;41 const struct iwl_fw_cmd_version *entry;
drivers/net/wireless/intel/iwlwifi/fw/img.h+8−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/types.h>9#include <linux/types.h>
10 10
11#include "api/dbg-tlv.h"11#include "api/dbg-tlv.h"
12#include "api/nvm-reg.h"
12 13
13#include "file.h"14#include "file.h"
14#include "error-dump.h"15#include "error-dump.h"
@@ -57,6 +58,9 @@ struct iwl_ucode_capabilities { · 42 unmodified lines
57 58
58 const struct iwl_fw_cmd_version *cmd_versions;59 const struct iwl_fw_cmd_version *cmd_versions;
59 u32 n_cmd_versions;60 u32 n_cmd_versions;
61
62 const struct iwl_fw_cmd_bios_table *cmd_bios_tables;
63 u32 n_cmd_bios_tables;
60};64};
61 65
62static inline bool66static inline bool
@@ -274,6 +278,10 @@ iwl_get_ucode_image(const struct iwl_fw *fw, enum iwl_ucode_type ucode_type) · 211 unmodified lines
274 return &fw->img[ucode_type];278 return &fw->img[ucode_type];
275}279}
276 280
281u8 iwl_fw_lookup_cmd_bios_supported_revision(const struct iwl_fw *fw,
282 enum bios_source table_source,
283 u32 cmd_id, u8 def);
284
277u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def);285u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def);
278 286
279u8 iwl_fw_lookup_notif_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def);287u8 iwl_fw_lookup_notif_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def);
drivers/net/wireless/intel/iwlwifi/fw/regulatory.c+25−126
@@ -241,6 +241,10 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt, · 240 unmodified lines
241 int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };241 int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };
242 int i, j;242 int i, j;
243 243
244 if (WARN_ON_ONCE(n_subbands >
245 ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands)))
246 return -EINVAL;
247
244 for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) {248 for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) {
245 struct iwl_sar_profile *prof;249 struct iwl_sar_profile *prof;
246 250
@@ -300,132 +304,6 @@ int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt, · 53 unmodified lines
300}304}
301IWL_EXPORT_SYMBOL(iwl_sar_fill_profile);305IWL_EXPORT_SYMBOL(iwl_sar_fill_profile);
302 306
303static bool iwl_ppag_value_valid(struct iwl_fw_runtime *fwrt, int chain,
304 int subband)
305{
306 s8 ppag_val = fwrt->ppag_chains[chain].subbands[subband];
307
308 if ((subband == 0 &&
309 (ppag_val > IWL_PPAG_MAX_LB || ppag_val < IWL_PPAG_MIN_LB)) ||
310 (subband != 0 &&
311 (ppag_val > IWL_PPAG_MAX_HB || ppag_val < IWL_PPAG_MIN_HB))) {
312 IWL_DEBUG_RADIO(fwrt, "Invalid PPAG value: %d\n", ppag_val);
313 return false;
314 }
315 return true;
316}
317
318/* Utility function for iwlmvm and iwlxvt */
319int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
320 union iwl_ppag_table_cmd *cmd, int *cmd_size)
321{
322 u8 cmd_ver;
323 int i, j, num_sub_bands;
324 s8 *gain;
325 bool send_ppag_always;
326
327 /* many firmware images for JF lie about this */
328 if (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id) ==
329 CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
330 return -EOPNOTSUPP;
331
332 if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
333 IWL_DEBUG_RADIO(fwrt,
334 "PPAG capability not supported by FW, command not sent.\n");
335 return -EINVAL;
336 }
337
338 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
339 WIDE_ID(PHY_OPS_GROUP,
340 PER_PLATFORM_ANT_GAIN_CMD), 1);
341 /*
342 * Starting from ver 4, driver needs to send the PPAG CMD regardless
343 * if PPAG is enabled/disabled or valid/invalid.
344 */
345 send_ppag_always = cmd_ver > 3;
346
347 /* Don't send PPAG if it is disabled */
348 if (!send_ppag_always && !fwrt->ppag_flags) {
349 IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
350 return -EINVAL;
351 }
352
353 IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
354 if (cmd_ver == 1) {
355 num_sub_bands = IWL_NUM_SUB_BANDS_V1;
356 gain = cmd->v1.gain[0];
357 *cmd_size = sizeof(cmd->v1);
358 cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK);
359 if (fwrt->ppag_bios_rev >= 1) {
360 /* in this case FW supports revision 0 */
361 IWL_DEBUG_RADIO(fwrt,
362 "PPAG table rev is %d, send truncated table\n",
363 fwrt->ppag_bios_rev);
364 }
365 } else if (cmd_ver == 5) {
366 num_sub_bands = IWL_NUM_SUB_BANDS_V2;
367 gain = cmd->v5.gain[0];
368 *cmd_size = sizeof(cmd->v5);
369 cmd->v5.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK);
370 if (fwrt->ppag_bios_rev == 0) {
371 /* in this case FW supports revisions 1,2 or 3 */
372 IWL_DEBUG_RADIO(fwrt,
373 "PPAG table rev is 0, send padded table\n");
374 }
375 } else if (cmd_ver == 7) {
376 num_sub_bands = IWL_NUM_SUB_BANDS_V2;
377 gain = cmd->v7.gain[0];
378 *cmd_size = sizeof(cmd->v7);
379 cmd->v7.ppag_config_info.hdr.table_source =
380 fwrt->ppag_bios_source;
381 cmd->v7.ppag_config_info.hdr.table_revision =
382 fwrt->ppag_bios_rev;
383 cmd->v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags);
384 } else {
385 IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
386 return -EINVAL;
387 }
388
389 /* ppag mode */
390 IWL_DEBUG_RADIO(fwrt,
391 "PPAG MODE bits were read from bios: %d\n",
392 fwrt->ppag_flags);
393
394 if (cmd_ver == 1 &&
395 !fw_has_capa(&fwrt->fw->ucode_capa,
396 IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) {
397 cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
398 IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
399 } else {
400 IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
401 }
402
403 /* The 'flags' field is the same in v1 and v5 so we can just
404 * use v1 to access it.
405 */
406 IWL_DEBUG_RADIO(fwrt,
407 "PPAG MODE bits going to be sent: %d\n",
408 (cmd_ver < 7) ? le32_to_cpu(cmd->v1.flags) :
409 le32_to_cpu(cmd->v7.ppag_config_info.value));
410
411 for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
412 for (j = 0; j < num_sub_bands; j++) {
413 if (!send_ppag_always &&
414 !iwl_ppag_value_valid(fwrt, i, j))
415 return -EINVAL;
416
417 gain[i * num_sub_bands + j] =
418 fwrt->ppag_chains[i].subbands[j];
419 IWL_DEBUG_RADIO(fwrt,
420 "PPAG table: chain[%d] band[%d]: gain = %d\n",
421 i, j, gain[i * num_sub_bands + j]);
422 }
423 }
424
425 return 0;
426}
427IWL_EXPORT_SYMBOL(iwl_fill_ppag_table);
428
429bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)307bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)
430{308{
431 if (!dmi_check_system(dmi_ppag_approved_list)) {309 if (!dmi_check_system(dmi_ppag_approved_list)) {
@@ -440,6 +318,27 @@ bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt) · 8 unmodified lines
440}318}
441IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);319IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);
442 320
321/* Print the PPAG table as read from BIOS */
322void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands)
323{
324 int i, j;
325
326 IWL_DEBUG_RADIO(fwrt, "PPAG table as read from BIOS:\n");
327 IWL_DEBUG_RADIO(fwrt, "PPAG revision = %d\n", fwrt->ppag_bios_rev);
328 IWL_DEBUG_RADIO(fwrt, "PPAG flags = 0x%x\n", fwrt->ppag_flags);
329
330 if (WARN_ON_ONCE(n_subbands >
331 ARRAY_SIZE(fwrt->ppag_chains[0].subbands)))
332 return;
333
334 for (i = 0; i < ARRAY_SIZE(fwrt->ppag_chains); i++)
335 for (j = 0; j < n_subbands; j++)
336 IWL_DEBUG_RADIO(fwrt,
337 "ppag_chains[%d].subbands[%d] = %d\n",
338 i, j,
339 fwrt->ppag_chains[i].subbands[j]);
340}
341
443bool iwl_is_tas_approved(void)342bool iwl_is_tas_approved(void)
444{343{
445 return dmi_check_system(dmi_tas_approved_list);344 return dmi_check_system(dmi_tas_approved_list);
drivers/net/wireless/intel/iwlwifi/fw/regulatory.h+7−7
@@ -21,10 +21,11 @@ · 20 unmodified lines
21 */21 */
22#define BIOS_SAR_MAX_CHAINS_PER_PROFILE 422#define BIOS_SAR_MAX_CHAINS_PER_PROFILE 4
23#define BIOS_SAR_NUM_CHAINS 223#define BIOS_SAR_NUM_CHAINS 2
24#define BIOS_SAR_MAX_SUB_BANDS_NUM 1124#define BIOS_SAR_MAX_SUB_BANDS_NUM 12
25#define BIOS_PPAG_MAX_SUB_BANDS_NUM 12
25 26
26#define BIOS_GEO_NUM_CHAINS 227#define BIOS_GEO_NUM_CHAINS 2
27#define BIOS_GEO_MAX_NUM_BANDS 328#define BIOS_GEO_MAX_NUM_BANDS 4
28#define BIOS_GEO_MAX_PROFILE_NUM 829#define BIOS_GEO_MAX_PROFILE_NUM 8
29#define BIOS_GEO_MIN_PROFILE_NUM 330#define BIOS_GEO_MIN_PROFILE_NUM 3
30 31
@@ -100,7 +101,7 @@ struct iwl_geo_profile { · 69 unmodified lines
100 101
101/* Same thing as with SAR, all revisions fit in revision 2 */102/* Same thing as with SAR, all revisions fit in revision 2 */
102struct iwl_ppag_chain {103struct iwl_ppag_chain {
103 s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];104 s8 subbands[BIOS_PPAG_MAX_SUB_BANDS_NUM];
104};105};
105 106
106struct iwl_tas_data {107struct iwl_tas_data {
@@ -180,6 +181,9 @@ enum iwl_dsm_masks_reg { · 73 unmodified lines
180 181
181struct iwl_fw_runtime;182struct iwl_fw_runtime;
182 183
184/* Print the PPAG table as read from BIOS */
185void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands);
186
183bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);187bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
184 188
185int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,189int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
@@ -190,10 +194,6 @@ int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt, · 4 unmodified lines
190 __le16 *per_chain, u32 n_tables, u32 n_subbands,194 __le16 *per_chain, u32 n_tables, u32 n_subbands,
191 int prof_a, int prof_b);195 int prof_a, int prof_b);
192 196
193int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
194 union iwl_ppag_table_cmd *cmd,
195 int *cmd_size);
196
197bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);197bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
198 198
199bool iwl_is_tas_approved(void);199bool iwl_is_tas_approved(void);
drivers/net/wireless/intel/iwlwifi/fw/runtime.h+6−4
@@ -106,13 +106,14 @@ struct iwl_txf_iter_data { · 105 unmodified lines
106 * @cur_fw_img: current firmware image, must be maintained by106 * @cur_fw_img: current firmware image, must be maintained by
107 * the driver by calling &iwl_fw_set_current_image()107 * the driver by calling &iwl_fw_set_current_image()
108 * @dump: debug dump data108 * @dump: debug dump data
109 * @uats_table: AP type table109 * @ap_type_cmd: AP type tables (for enablement on 6 GHz)
110 * @uats_valid: is AP type table valid110 * @ap_type_cmd_valid: if &ap_type_cmd is valid
111 * @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock:111 * @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock:
112 * 0: Unlocked, 1 and 2: Locked.112 * 0: Unlocked, 1 and 2: Locked.
113 * Only read the UEFI variables if locked.113 * Only read the UEFI variables if locked.
114 * @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables114 * @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables
115 * @geo_profiles: geographic profiles as read from WGDS BIOS table115 * @geo_profiles: geographic profiles as read from WGDS BIOS table
116 * @geo_bios_source: see &enum bios_source
116 * @phy_filters: specific phy filters as read from WPFC BIOS table117 * @phy_filters: specific phy filters as read from WPFC BIOS table
117 * @ppag_bios_rev: PPAG BIOS revision118 * @ppag_bios_rev: PPAG BIOS revision
118 * @ppag_bios_source: see &enum bios_source119 * @ppag_bios_source: see &enum bios_source
@@ -204,6 +205,7 @@ struct iwl_fw_runtime { · 85 unmodified lines
204 u8 sar_chain_b_profile;205 u8 sar_chain_b_profile;
205 u8 reduced_power_flags;206 u8 reduced_power_flags;
206 struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];207 struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
208 enum bios_source geo_bios_source;
207 u32 geo_rev;209 u32 geo_rev;
208 u32 geo_num_profiles;210 u32 geo_num_profiles;
209 bool geo_enabled;211 bool geo_enabled;
@@ -213,8 +215,8 @@ struct iwl_fw_runtime { · 3 unmodified lines
213 u8 ppag_bios_source;215 u8 ppag_bios_source;
214 struct iwl_sar_offset_mapping_cmd sgom_table;216 struct iwl_sar_offset_mapping_cmd sgom_table;
215 bool sgom_enabled;217 bool sgom_enabled;
216 struct iwl_mcc_allowed_ap_type_cmd uats_table;218 struct iwl_mcc_allowed_ap_type_cmd ap_type_cmd;
217 bool uats_valid;219 bool ap_type_cmd_valid;
218 u8 uefi_tables_lock_status;220 u8 uefi_tables_lock_status;
219 struct iwl_phy_specific_cfg phy_filters;221 struct iwl_phy_specific_cfg phy_filters;
220 enum bios_source dsm_source;222 enum bios_source dsm_source;
drivers/net/wireless/intel/iwlwifi/fw/uefi.c+202−34
@@ -402,11 +402,11 @@ static int iwl_uefi_uats_parse(struct uefi_cnv_wlan_uats_data *uats_data, · 401 unmodified lines
402 if (uats_data->revision != 1)402 if (uats_data->revision != 1)
403 return -EINVAL;403 return -EINVAL;
404 404
405 memcpy(fwrt->uats_table.mcc_to_ap_type_map,405 memcpy(fwrt->ap_type_cmd.mcc_to_ap_type_map,
406 uats_data->mcc_to_ap_type_map,406 uats_data->mcc_to_ap_type_map,
407 sizeof(fwrt->uats_table.mcc_to_ap_type_map));407 sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_map));
408 408
409 fwrt->uats_valid = true;409 fwrt->ap_type_cmd_valid = true;
410 410
411 return 0;411 return 0;
412}412}
@@ -429,12 +429,61 @@ void iwl_uefi_get_uats_table(struct iwl_trans *trans, · 16 unmodified lines
429}429}
430IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table);430IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table);
431 431
432void iwl_uefi_get_uneb_table(struct iwl_trans *trans,
433 struct iwl_fw_runtime *fwrt)
434{
435 struct uefi_cnv_wlan_uneb_data *data;
436
437 data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UNEB_NAME,
438 "UNEB", sizeof(*data), NULL);
439 if (IS_ERR(data))
440 return;
441
442 if (data->revision != 1) {
443 IWL_DEBUG_RADIO(fwrt,
444 "Cannot read UNEB table. rev is invalid\n");
445 goto out;
446 }
447
448 BUILD_BUG_ON(sizeof(data->mcc_to_ap_type_map) !=
449 sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map));
450
451 memcpy(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map,
452 data->mcc_to_ap_type_map,
453 sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map));
454
455 fwrt->ap_type_cmd_valid = true;
456
457out:
458 kfree(data);
459}
460IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table);
461
432static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,462static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,
433 struct uefi_sar_profile *uefi_sar_prof,463 const u8 *vals, u8 prof_index,
434 u8 prof_index, bool enabled)464 u8 num_subbands, bool enabled)
435{465{
436 memcpy(&fwrt->sar_profiles[prof_index].chains, uefi_sar_prof,466 struct iwl_sar_profile *sar_prof = &fwrt->sar_profiles[prof_index];
437 sizeof(struct uefi_sar_profile));467
468 /*
469 * Make sure fwrt has enough room to hold the data
470 * coming from the UEFI table
471 */
472 if (WARN_ON(ARRAY_SIZE(sar_prof->chains) *
473 ARRAY_SIZE(sar_prof->chains[0].subbands) <
474 UEFI_SAR_MAX_CHAINS_PER_PROFILE * num_subbands))
475 return;
476
477 BUILD_BUG_ON(ARRAY_SIZE(sar_prof->chains) !=
478 UEFI_SAR_MAX_CHAINS_PER_PROFILE);
479
480 for (int chain = 0;
481 chain < UEFI_SAR_MAX_CHAINS_PER_PROFILE;
482 chain++) {
483 for (int subband = 0; subband < num_subbands; subband++)
484 sar_prof->chains[chain].subbands[subband] =
485 vals[chain * num_subbands + subband];
486 }
438 487
439 fwrt->sar_profiles[prof_index].enabled = enabled & IWL_SAR_ENABLE_MSK;488 fwrt->sar_profiles[prof_index].enabled = enabled & IWL_SAR_ENABLE_MSK;
440}489}
@@ -442,24 +491,46 @@ static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt, · 1 unmodified line
442int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)491int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
443{492{
444 struct uefi_cnv_var_wrds *data;493 struct uefi_cnv_var_wrds *data;
494 unsigned long size;
495 unsigned long expected_size;
496 int num_subbands;
445 int ret = 0;497 int ret = 0;
446 498
447 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WRDS_NAME,499 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WRDS_NAME,
448 "WRDS", sizeof(*data), NULL);500 "WRDS",
501 UEFI_SAR_WRDS_TABLE_SIZE_REV2,
502 &size);
503
449 if (IS_ERR(data))504 if (IS_ERR(data))
450 return -EINVAL;505 return -EINVAL;
451 506
452 if (data->revision != IWL_UEFI_WRDS_REVISION) {507 switch (data->revision) {
453 ret = -EINVAL;508 case 2:
454 IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WRDS revision:%d\n",509 expected_size = UEFI_SAR_WRDS_TABLE_SIZE_REV2;
510 num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV2;
511 break;
512 case 3:
513 expected_size = UEFI_SAR_WRDS_TABLE_SIZE_REV3;
514 num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV3;
515 break;
516 default:
517 IWL_DEBUG_RADIO(fwrt,
518 "Unsupported UEFI WRDS revision:%d\n",
455 data->revision);519 data->revision);
520 ret = -EINVAL;
521 goto out;
522 }
523
524 if (size != expected_size) {
525 ret = -EINVAL;
456 goto out;526 goto out;
457 }527 }
458 528
459 /* The profile from WRDS is officially profile 1, but goes529 /* The profile from WRDS is officially profile 1, but goes
460 * into sar_profiles[0] (because we don't have a profile 0).530 * into sar_profiles[0] (because we don't have a profile 0).
461 */531 */
462 iwl_uefi_set_sar_profile(fwrt, &data->sar_profile, 0, data->mode);532 iwl_uefi_set_sar_profile(fwrt, data->vals, 0,
533 num_subbands, data->mode);
463out:534out:
464 kfree(data);535 kfree(data);
465 return ret;536 return ret;
@@ -468,21 +539,40 @@ out: · 2 unmodified lines
468int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)539int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
469{540{
470 struct uefi_cnv_var_ewrd *data;541 struct uefi_cnv_var_ewrd *data;
542 unsigned long expected_size;
471 int i, ret = 0;543 int i, ret = 0;
544 unsigned long size;
545 int num_subbands;
546 int profile_size;
472 547
473 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_EWRD_NAME,548 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_EWRD_NAME,
474 "EWRD", sizeof(*data), NULL);549 "EWRD",
550 UEFI_SAR_EWRD_TABLE_SIZE_REV2,
551 &size);
475 if (IS_ERR(data))552 if (IS_ERR(data))
476 return -EINVAL;553 return -EINVAL;
477 554
478 if (data->revision != IWL_UEFI_EWRD_REVISION) {555 switch (data->revision) {
479 ret = -EINVAL;556 case 2:
480 IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI EWRD revision:%d\n",557 expected_size = UEFI_SAR_EWRD_TABLE_SIZE_REV2;
558 num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV2;
559 profile_size = UEFI_SAR_PROFILE_SIZE_REV2;
560 break;
561 case 3:
562 expected_size = UEFI_SAR_EWRD_TABLE_SIZE_REV3;
563 num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV3;
564 profile_size = UEFI_SAR_PROFILE_SIZE_REV3;
565 break;
566 default:
567 IWL_DEBUG_RADIO(fwrt,
568 "Unsupported UEFI EWRD revision:%d\n",
481 data->revision);569 data->revision);
570 ret = -EINVAL;
482 goto out;571 goto out;
483 }572 }
484 573
485 if (data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {574 if (size != expected_size ||
575 data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {
486 ret = -EINVAL;576 ret = -EINVAL;
487 goto out;577 goto out;
488 }578 }
@@ -492,8 +582,8 @@ int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt) · 3 unmodified lines
492 * save them in sar_profiles[1-3] (because we don't582 * save them in sar_profiles[1-3] (because we don't
493 * have profile 0). So in the array we start from 1.583 * have profile 0). So in the array we start from 1.
494 */584 */
495 iwl_uefi_set_sar_profile(fwrt, &data->sar_profiles[i], i + 1,585 iwl_uefi_set_sar_profile(fwrt, &data->vals[i * profile_size],
496 data->mode);586 i + 1, num_subbands, data->mode);
497 587
498out:588out:
499 kfree(data);589 kfree(data);
@@ -503,20 +593,39 @@ out: · 3 unmodified lines
503int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)593int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
504{594{
505 struct uefi_cnv_var_wgds *data;595 struct uefi_cnv_var_wgds *data;
506 int i, ret = 0;596 unsigned long expected_size;
597 unsigned long size;
598 int profile_size;
599 int n_subbands;
600 int ret = 0;
507 601
508 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WGDS_NAME,602 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WGDS_NAME,
509 "WGDS", sizeof(*data), NULL);603 "WGDS", UEFI_WGDS_TABLE_SIZE_REV3,
604 &size);
510 if (IS_ERR(data))605 if (IS_ERR(data))
511 return -EINVAL;606 return -EINVAL;
512 607
513 if (data->revision != IWL_UEFI_WGDS_REVISION) {608 switch (data->revision) {
609 case 3:
610 expected_size = UEFI_WGDS_TABLE_SIZE_REV3;
611 n_subbands = UEFI_GEO_NUM_BANDS_REV3;
612 break;
613 case 4:
614 expected_size = UEFI_WGDS_TABLE_SIZE_REV4;
615 n_subbands = UEFI_GEO_NUM_BANDS_REV4;
616 break;
617 default:
514 ret = -EINVAL;618 ret = -EINVAL;
515 IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WGDS revision:%d\n",619 IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WGDS revision:%d\n",
516 data->revision);620 data->revision);
517 goto out;621 goto out;
518 }622 }
519 623
624 if (size != expected_size) {
625 ret = -EINVAL;
626 goto out;
627 }
628
520 if (data->num_profiles < BIOS_GEO_MIN_PROFILE_NUM ||629 if (data->num_profiles < BIOS_GEO_MIN_PROFILE_NUM ||
521 data->num_profiles > BIOS_GEO_MAX_PROFILE_NUM) {630 data->num_profiles > BIOS_GEO_MAX_PROFILE_NUM) {
522 ret = -EINVAL;631 ret = -EINVAL;
@@ -525,10 +634,31 @@ int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt) · 2 unmodified lines
525 goto out;634 goto out;
526 }635 }
527 636
637 if (WARN_ON(BIOS_GEO_MAX_PROFILE_NUM >
638 ARRAY_SIZE(fwrt->geo_profiles) ||
639 n_subbands > ARRAY_SIZE(fwrt->geo_profiles[0].bands) ||
640 BIOS_GEO_NUM_CHAINS >
641 ARRAY_SIZE(fwrt->geo_profiles[0].bands[0].chains))) {
642 ret = -EINVAL;
643 goto out;
644 }
645
528 fwrt->geo_rev = data->revision;646 fwrt->geo_rev = data->revision;
529 for (i = 0; i < data->num_profiles; i++)647 fwrt->geo_bios_source = BIOS_SOURCE_UEFI;
530 memcpy(&fwrt->geo_profiles[i], &data->geo_profiles[i],648 profile_size = 3 * n_subbands;
531 sizeof(struct iwl_geo_profile));649 for (int prof = 0; prof < data->num_profiles; prof++) {
650 const u8 *val = &data->vals[profile_size * prof];
651 struct iwl_geo_profile *geo_prof = &fwrt->geo_profiles[prof];
652
653 for (int subband = 0; subband < n_subbands; subband++) {
654 geo_prof->bands[subband].max = *val++;
655
656 for (int chain = 0;
657 chain < BIOS_GEO_NUM_CHAINS;
658 chain++)
659 geo_prof->bands[subband].chains[chain] = *val++;
660 }
661 }
532 662
533 fwrt->geo_num_profiles = data->num_profiles;663 fwrt->geo_num_profiles = data->num_profiles;
534 fwrt->geo_enabled = true;664 fwrt->geo_enabled = true;
@@ -540,28 +670,66 @@ out: · 5 unmodified lines
540int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)670int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
541{671{
542 struct uefi_cnv_var_ppag *data;672 struct uefi_cnv_var_ppag *data;
673 int n_subbands;
674 u32 valid_rev;
543 int ret = 0;675 int ret = 0;
544 676
545 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME,677 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME,
546 "PPAG", sizeof(*data), NULL);678 "PPAG", UEFI_PPAG_DATA_SIZE_V5,
547 if (IS_ERR(data))679 NULL);
548 return -EINVAL;680 if (!IS_ERR(data)) {
681 n_subbands = UEFI_PPAG_SUB_BANDS_NUM_REV5;
682 valid_rev = BIT(5);
683
684 goto parse_table;
685 }
686
687 data = iwl_uefi_get_verified_variable(fwrt->trans,
688 IWL_UEFI_PPAG_NAME,
689 "PPAG",
690 UEFI_PPAG_DATA_SIZE_V4,
691 NULL);
692 if (!IS_ERR(data)) {
693 n_subbands = UEFI_PPAG_SUB_BANDS_NUM_REV4;
694 /* revisions 1-4 have all the same size */
695 valid_rev = BIT(1) | BIT(2) | BIT(3) | BIT(4);
696
697 goto parse_table;
698 }
549 699
550 if (data->revision < IWL_UEFI_MIN_PPAG_REV ||700 return -EINVAL;
551 data->revision > IWL_UEFI_MAX_PPAG_REV) {701
702parse_table:
703 if (!(BIT(data->revision) & valid_rev)) {
552 ret = -EINVAL;704 ret = -EINVAL;
553 IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI PPAG revision:%d\n",705 IWL_DEBUG_RADIO(fwrt,
706 "Unsupported UEFI PPAG revision:%d\n",
554 data->revision);707 data->revision);
555 goto out;708 goto out;
556 }709 }
557 710
711 /*
712 * Make sure fwrt has enough room to hold
713 * data coming from the UEFI table
714 */
715 if (WARN_ON(ARRAY_SIZE(fwrt->ppag_chains) *
716 ARRAY_SIZE(fwrt->ppag_chains[0].subbands) <
717 UEFI_PPAG_NUM_CHAINS * n_subbands)) {
718 ret = -EINVAL;
719 goto out;
720 }
721
558 fwrt->ppag_bios_rev = data->revision;722 fwrt->ppag_bios_rev = data->revision;
559 fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes,723 fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes,
560 fwrt->ppag_bios_rev);724 fwrt->ppag_bios_rev);
561 725
562 BUILD_BUG_ON(sizeof(fwrt->ppag_chains) != sizeof(data->ppag_chains));726 for (int chain = 0; chain < UEFI_PPAG_NUM_CHAINS; chain++) {
563 memcpy(&fwrt->ppag_chains, &data->ppag_chains,727 for (int subband = 0; subband < n_subbands; subband++)
564 sizeof(data->ppag_chains));728 fwrt->ppag_chains[chain].subbands[subband] =
729 data->vals[chain * n_subbands + subband];
730 }
731
732 iwl_bios_print_ppag(fwrt, n_subbands);
565 fwrt->ppag_bios_source = BIOS_SOURCE_UEFI;733 fwrt->ppag_bios_source = BIOS_SOURCE_UEFI;
566out:734out:
567 kfree(data);735 kfree(data);
drivers/net/wireless/intel/iwlwifi/fw/uefi.h+110−31
@@ -25,16 +25,12 @@ · 24 unmodified lines
25#define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing"25#define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing"
26#define IWL_UEFI_DSBR_NAME L"UefiCnvCommonDSBR"26#define IWL_UEFI_DSBR_NAME L"UefiCnvCommonDSBR"
27#define IWL_UEFI_WPFC_NAME L"WPFC"27#define IWL_UEFI_WPFC_NAME L"WPFC"
28#define IWL_UEFI_UNEB_NAME L"CnvUefiWlanUNEB"
28 29
29 30
30#define IWL_SGOM_MAP_SIZE 33931#define IWL_SGOM_MAP_SIZE 339
31#define IWL_UATS_MAP_SIZE 33932#define IWL_UATS_MAP_SIZE 339
32 33
33#define IWL_UEFI_WRDS_REVISION 2
34#define IWL_UEFI_EWRD_REVISION 2
35#define IWL_UEFI_WGDS_REVISION 3
36#define IWL_UEFI_MIN_PPAG_REV 1
37#define IWL_UEFI_MAX_PPAG_REV 4
38#define IWL_UEFI_MIN_WTAS_REVISION 134#define IWL_UEFI_MIN_WTAS_REVISION 1
39#define IWL_UEFI_MAX_WTAS_REVISION 235#define IWL_UEFI_MAX_WTAS_REVISION 2
40#define IWL_UEFI_SPLC_REVISION 036#define IWL_UEFI_SPLC_REVISION 0
@@ -63,6 +59,9 @@ struct uefi_cnv_wlan_uats_data { · 22 unmodified lines
63 u8 mcc_to_ap_type_map[IWL_UATS_MAP_SIZE - 1];59 u8 mcc_to_ap_type_map[IWL_UATS_MAP_SIZE - 1];
64} __packed;60} __packed;
65 61
62/* UNEB's layout is identical to UATS's */
63#define uefi_cnv_wlan_uneb_data uefi_cnv_wlan_uats_data
64
66struct uefi_cnv_common_step_data {65struct uefi_cnv_common_step_data {
67 u8 revision;66 u8 revision;
68 u8 step_mode;67 u8 step_mode;
@@ -72,68 +71,135 @@ struct uefi_cnv_common_step_data { · 3 unmodified lines
72 u8 radio2;71 u8 radio2;
73} __packed;72} __packed;
74 73
75/*74#define UEFI_PPAG_SUB_BANDS_NUM_REV4 11
76 * struct uefi_sar_profile - a SAR profile as defined in UEFI75#define UEFI_PPAG_SUB_BANDS_NUM_REV5 12
77 *76#define UEFI_PPAG_NUM_CHAINS 2
78 * @chains: a per-chain table of SAR values
79 */
80struct uefi_sar_profile {
81 struct iwl_sar_profile_chain chains[BIOS_SAR_MAX_CHAINS_PER_PROFILE];
82} __packed;
83 77
84/*78#define UEFI_SAR_SUB_BANDS_NUM_REV2 11
79#define UEFI_SAR_SUB_BANDS_NUM_REV3 12
80
81#define UEFI_SAR_MAX_CHAINS_PER_PROFILE 4
82
83#define UEFI_GEO_NUM_BANDS_REV3 3
84#define UEFI_GEO_NUM_BANDS_REV4 4
85
86/**
85 * struct uefi_cnv_var_wrds - WRDS table as defined in UEFI87 * struct uefi_cnv_var_wrds - WRDS table as defined in UEFI
86 *88 *
87 * @revision: the revision of the table89 * @revision: the revision of the table
88 * @mode: is WRDS enbaled/disabled90 * @mode: is WRDS enbaled/disabled
89 * @sar_profile: sar profile #191 * @vals: values for sar profile #1 as an array:
92 * vals[chain * num_of_subbands + subband] will return the right value.
93 * num_of_subbands depends on the revision. For revision 3, it is
94 * %UEFI_SAR_SUB_BANDS_NUM_REV3, for earlier revision, it is
95 * %UEFI_SAR_SUB_BANDS_NUM_REV2.
96 * The max number of chains is currently 2
90 */97 */
91struct uefi_cnv_var_wrds {98struct uefi_cnv_var_wrds {
92 u8 revision;99 u8 revision;
93 u32 mode;100 u32 mode;
94 struct uefi_sar_profile sar_profile;101 u8 vals[];
95} __packed;102} __packed;
96 103
97/*104#define UEFI_SAR_PROFILE_SIZE_REV2 \
105 (sizeof(u8) * UEFI_SAR_MAX_CHAINS_PER_PROFILE * \
106 UEFI_SAR_SUB_BANDS_NUM_REV2)
107
108#define UEFI_SAR_PROFILE_SIZE_REV3 \
109 (sizeof(u8) * UEFI_SAR_MAX_CHAINS_PER_PROFILE * \
110 UEFI_SAR_SUB_BANDS_NUM_REV3)
111
112#define UEFI_SAR_WRDS_TABLE_SIZE_REV2 \
113 (offsetof(struct uefi_cnv_var_wrds, vals) + \
114 UEFI_SAR_PROFILE_SIZE_REV2)
115
116#define UEFI_SAR_WRDS_TABLE_SIZE_REV3 \
117 (offsetof(struct uefi_cnv_var_wrds, vals) + \
118 UEFI_SAR_PROFILE_SIZE_REV3)
119
120/**
98 * struct uefi_cnv_var_ewrd - EWRD table as defined in UEFI121 * struct uefi_cnv_var_ewrd - EWRD table as defined in UEFI
99 * @revision: the revision of the table122 * @revision: the revision of the table
100 * @mode: is WRDS enbaled/disabled123 * @mode: is WRDS enbaled/disabled
101 * @num_profiles: how many additional profiles we have in this table (0-3)124 * @num_profiles: how many additional profiles we have in this table (0-3)
102 * @sar_profiles: the additional SAR profiles (#2-#4)125 * @vals: the additional SAR profiles (#2-#4) as an array of SAR profiles.
126 * A SAR profile is defined the &struct uefi_cnv_var_wrds::vals. The size
127 * of each profile depends on the number of subbands which depends on the
128 * revision. This is explained in &struct uefi_cnv_var_wrds.
103 */129 */
104struct uefi_cnv_var_ewrd {130struct uefi_cnv_var_ewrd {
105 u8 revision;131 u8 revision;
106 u32 mode;132 u32 mode;
107 u32 num_profiles;133 u32 num_profiles;
108 struct uefi_sar_profile sar_profiles[BIOS_SAR_MAX_PROFILE_NUM - 1];134 u8 vals[];
109} __packed;135} __packed;
110 136
111/*137#define UEFI_SAR_EWRD_TABLE_SIZE_REV2 \
138 (offsetof(struct uefi_cnv_var_ewrd, vals) + \
139 UEFI_SAR_PROFILE_SIZE_REV2 * (BIOS_SAR_MAX_PROFILE_NUM - 1))
140
141#define UEFI_SAR_EWRD_TABLE_SIZE_REV3 \
142 (offsetof(struct uefi_cnv_var_ewrd, vals) + \
143 UEFI_SAR_PROFILE_SIZE_REV3 * (BIOS_SAR_MAX_PROFILE_NUM - 1))
144
145/**
112 * struct uefi_cnv_var_wgds - WGDS table as defined in UEFI146 * struct uefi_cnv_var_wgds - WGDS table as defined in UEFI
113 * @revision: the revision of the table147 * @revision: the revision of the table
114 * @num_profiles: the number of geo profiles we have in the table.148 * @num_profiles: the number of geo profiles we have in the table.
115 * The first 3 are mandatory, and can have up to 8.149 * The first 3 are mandatory, and can have up to 8.
116 * @geo_profiles: a per-profile table of the offsets to add to SAR values.150 * @vals: a per-profile table of the offsets to add to SAR values. This is an
151 * array of profiles, each profile is an array of
152 * &struct iwl_geo_profile_band, one for each subband.
153 * There are %UEFI_GEO_NUM_BANDS_REV3 or %UEFI_GEO_NUM_BANDS_REV4 subbands
154 * depending on the revision.
117 */155 */
118struct uefi_cnv_var_wgds {156struct uefi_cnv_var_wgds {
119 u8 revision;157 u8 revision;
120 u8 num_profiles;158 u8 num_profiles;
121 struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];159 u8 vals[];
122} __packed;160} __packed;
123 161
124/*162/* struct iwl_geo_profile_band is 3 bytes-long, but since it is not packed,
163 * we can't use sizeof()
164 */
165#define UEFI_WGDS_PROFILE_SIZE_REV3 (sizeof(u8) * 3 * UEFI_GEO_NUM_BANDS_REV3)
166
167#define UEFI_WGDS_PROFILE_SIZE_REV4 (sizeof(u8) * 3 * UEFI_GEO_NUM_BANDS_REV4)
168
169#define UEFI_WGDS_TABLE_SIZE_REV3 \
170 (offsetof(struct uefi_cnv_var_wgds, vals) + \
171 UEFI_WGDS_PROFILE_SIZE_REV3 * BIOS_GEO_MAX_PROFILE_NUM)
172
173#define UEFI_WGDS_TABLE_SIZE_REV4 \
174 (offsetof(struct uefi_cnv_var_wgds, vals) + \
175 UEFI_WGDS_PROFILE_SIZE_REV4 * BIOS_GEO_MAX_PROFILE_NUM)
176
177/**
125 * struct uefi_cnv_var_ppag - PPAG table as defined in UEFI178 * struct uefi_cnv_var_ppag - PPAG table as defined in UEFI
126 * @revision: the revision of the table179 * @revision: the revision of the table
127 * @ppag_modes: values from &enum iwl_ppag_flags180 * @ppag_modes: values from &enum iwl_ppag_flags
128 * @ppag_chains: the PPAG values per chain and band181 * @vals: the PPAG values per chain and band as an array.
182 * vals[chain * num_of_subbands + subband] will return the right value.
183 * num_of_subbands depends on the revision. For revision 5, it is
184 * %UEFI_PPAG_SUB_BANDS_NUM_REV5, for earlier revision it is
185 * %UEFI_PPAG_SUB_BANDS_NUM_REV4.
186 * the max number of chains is currently 2
129 */187 */
130struct uefi_cnv_var_ppag {188struct uefi_cnv_var_ppag {
131 u8 revision;189 u8 revision;
132 u32 ppag_modes;190 u32 ppag_modes;
133 struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];191 s8 vals[];
134} __packed;192} __packed;
135 193
136/* struct uefi_cnv_var_wtas - WTAS tabled as defined in UEFI194#define UEFI_PPAG_DATA_SIZE_V4 \
195 (offsetof(struct uefi_cnv_var_ppag, vals) + \
196 sizeof(s8) * UEFI_PPAG_NUM_CHAINS * UEFI_PPAG_SUB_BANDS_NUM_REV4)
197#define UEFI_PPAG_DATA_SIZE_V5 \
198 (offsetof(struct uefi_cnv_var_ppag, vals) + \
199 sizeof(s8) * UEFI_PPAG_NUM_CHAINS * UEFI_PPAG_SUB_BANDS_NUM_REV5)
200
201/**
202 * struct uefi_cnv_var_wtas - WTAS tabled as defined in UEFI
137 * @revision: the revision of the table203 * @revision: the revision of the table
138 * @tas_selection: different options of TAS enablement.204 * @tas_selection: different options of TAS enablement.
139 * @black_list_size: the number of defined entried in the black list205 * @black_list_size: the number of defined entried in the black list
@@ -146,7 +212,8 @@ struct uefi_cnv_var_wtas { · 6 unmodified lines
146 u16 black_list[IWL_WTAS_BLACK_LIST_MAX];212 u16 black_list[IWL_WTAS_BLACK_LIST_MAX];
147} __packed;213} __packed;
148 214
149/* struct uefi_cnv_var_splc - SPLC tabled as defined in UEFI215/**
216 * struct uefi_cnv_var_splc - SPLC tabled as defined in UEFI
150 * @revision: the revision of the table217 * @revision: the revision of the table
151 * @default_pwr_limit: The default maximum power per device218 * @default_pwr_limit: The default maximum power per device
152 */219 */
@@ -155,7 +222,8 @@ struct uefi_cnv_var_splc { · 2 unmodified lines
155 u32 default_pwr_limit;222 u32 default_pwr_limit;
156} __packed;223} __packed;
157 224
158/* struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI225/**
226 * struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI
159 * @revision: the revision of the table227 * @revision: the revision of the table
160 * @mcc: country identifier as defined in ISO/IEC 3166-1 Alpha 2 code228 * @mcc: country identifier as defined in ISO/IEC 3166-1 Alpha 2 code
161 */229 */
@@ -164,7 +232,8 @@ struct uefi_cnv_var_wrdd { · 2 unmodified lines
164 u32 mcc;232 u32 mcc;
165} __packed;233} __packed;
166 234
167/* struct uefi_cnv_var_eckv - ECKV table as defined in UEFI235/**
236 * struct uefi_cnv_var_eckv - ECKV table as defined in UEFI
168 * @revision: the revision of the table237 * @revision: the revision of the table
169 * @ext_clock_valid: indicates if external 32KHz clock is valid238 * @ext_clock_valid: indicates if external 32KHz clock is valid
170 */239 */
@@ -175,7 +244,8 @@ struct uefi_cnv_var_eckv { · 4 unmodified lines
175 244
176#define UEFI_MAX_DSM_FUNCS 32245#define UEFI_MAX_DSM_FUNCS 32
177 246
178/* struct uefi_cnv_var_general_cfg - DSM-like table as defined in UEFI247/**
248 * struct uefi_cnv_var_general_cfg - DSM-like table as defined in UEFI
179 * @revision: the revision of the table249 * @revision: the revision of the table
180 * @functions: payload of the different DSM functions250 * @functions: payload of the different DSM functions
181 */251 */
@@ -185,7 +255,9 @@ struct uefi_cnv_var_general_cfg { · 3 unmodified lines
185} __packed;255} __packed;
186 256
187#define IWL_UEFI_WBEM_REV0_MASK (BIT(0) | BIT(1))257#define IWL_UEFI_WBEM_REV0_MASK (BIT(0) | BIT(1))
188/* struct uefi_cnv_wlan_wbem_data - Bandwidth enablement per MCC as defined258
259/**
260 * struct uefi_cnv_wlan_wbem_data - Bandwidth enablement per MCC as defined
189 * in UEFI261 * in UEFI
190 * @revision: the revision of the table262 * @revision: the revision of the table
191 * @wbem_320mhz_per_mcc: enablement of 320MHz bandwidth per MCC263 * @wbem_320mhz_per_mcc: enablement of 320MHz bandwidth per MCC
@@ -274,6 +346,8 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func, · 82 unmodified lines
274void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);346void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
275void iwl_uefi_get_uats_table(struct iwl_trans *trans,347void iwl_uefi_get_uats_table(struct iwl_trans *trans,
276 struct iwl_fw_runtime *fwrt);348 struct iwl_fw_runtime *fwrt);
349void iwl_uefi_get_uneb_table(struct iwl_trans *trans,
350 struct iwl_fw_runtime *fwrt);
277int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);351int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);
278int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);352int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
279int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt);353int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt);
@@ -373,6 +447,11 @@ iwl_uefi_get_uats_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt) · 93 unmodified lines
373{447{
374}448}
375 449
450static inline void
451iwl_uefi_get_uneb_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
452{
453}
454
376static inline455static inline
377int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)456int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
378{457{
drivers/net/wireless/intel/iwlwifi/iwl-config.h+0−1
@@ -85,7 +85,6 @@ enum iwl_nvm_type { · 84 unmodified lines
85#define IWL_WATCHDOG_DISABLED 085#define IWL_WATCHDOG_DISABLED 0
86#define IWL_DEF_WD_TIMEOUT 250086#define IWL_DEF_WD_TIMEOUT 2500
87#define IWL_LONG_WD_TIMEOUT 1000087#define IWL_LONG_WD_TIMEOUT 10000
88#define IWL_MAX_WD_TIMEOUT 120000
89 88
90#define IWL_DEFAULT_MAX_TX_POWER 2289#define IWL_DEFAULT_MAX_TX_POWER 22
91#define IWL_TX_CSUM_NETIF_FLAGS (NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM |\90#define IWL_TX_CSUM_NETIF_FLAGS (NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM |\
drivers/net/wireless/intel/iwlwifi/iwl-drv.c+22−1
@@ -133,6 +133,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) · 132 unmodified lines
133 kfree(drv->fw.dbg.mem_tlv);133 kfree(drv->fw.dbg.mem_tlv);
134 kfree(drv->fw.iml);134 kfree(drv->fw.iml);
135 kfree(drv->fw.ucode_capa.cmd_versions);135 kfree(drv->fw.ucode_capa.cmd_versions);
136 kfree(drv->fw.ucode_capa.cmd_bios_tables);
136 kfree(drv->fw.phy_integration_ver);137 kfree(drv->fw.phy_integration_ver);
137 kfree(drv->trans->dbg.pc_data);138 kfree(drv->trans->dbg.pc_data);
138 drv->trans->dbg.pc_data = NULL;139 drv->trans->dbg.pc_data = NULL;
@@ -1314,7 +1315,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, · 1175 unmodified lines
1314 if (tlv_len != sizeof(u32))1315 if (tlv_len != sizeof(u32))
1315 goto invalid_tlv_len;1316 goto invalid_tlv_len;
1316 if (le32_to_cpup((const __le32 *)tlv_data) >1317 if (le32_to_cpup((const __le32 *)tlv_data) >
1317 IWL_FW_MAX_LINK_ID + 1) {1318 IWL_FW_MAX_LINKS) {
1318 IWL_ERR(drv,1319 IWL_ERR(drv,
1319 "%d is an invalid number of links\n",1320 "%d is an invalid number of links\n",
1320 le32_to_cpup((const __le32 *)tlv_data));1321 le32_to_cpup((const __le32 *)tlv_data));
@@ -1426,6 +1427,26 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, · 105 unmodified lines
1426 return -ENOMEM;1427 return -ENOMEM;
1427 drv->fw.pnvm_size = tlv_len;1428 drv->fw.pnvm_size = tlv_len;
1428 break;1429 break;
1430 case IWL_UCODE_TLV_CMD_BIOS_TABLE:
1431 if (tlv_len % sizeof(struct iwl_fw_cmd_bios_table)) {
1432 IWL_ERR(drv,
1433 "Invalid length for command bios table: %u\n",
1434 tlv_len);
1435 return -EINVAL;
1436 }
1437
1438 if (capa->cmd_bios_tables) {
1439 IWL_ERR(drv, "Duplicate TLV type 0x%02X detected\n",
1440 tlv_type);
1441 return -EINVAL;
1442 }
1443 capa->cmd_bios_tables = kmemdup(tlv_data, tlv_len,
1444 GFP_KERNEL);
1445 if (!capa->cmd_bios_tables)
1446 return -ENOMEM;
1447 capa->n_cmd_bios_tables =
1448 tlv_len / sizeof(struct iwl_fw_cmd_bios_table);
1449 break;
1429 default:1450 default:
1430 IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);1451 IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
1431 break;1452 break;
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c+8−1
@@ -23,6 +23,8 @@ · 22 unmodified lines
23#include "fw/api/commands.h"23#include "fw/api/commands.h"
24#include "fw/api/cmdhdr.h"24#include "fw/api/cmdhdr.h"
25#include "fw/img.h"25#include "fw/img.h"
26#include "fw/dbg.h"
27
26#include "mei/iwl-mei.h"28#include "mei/iwl-mei.h"
27 29
28/* NVM offsets (in words) definitions */30/* NVM offsets (in words) definitions */
@@ -1702,6 +1704,11 @@ iwl_parse_nvm_mcc_info(struct iwl_trans *trans, · 1673 unmodified lines
1702 band);1704 band);
1703 new_rule = false;1705 new_rule = false;
1704 1706
1707 if (IWL_FW_CHECK(trans, !center_freq,
1708 "Invalid channel %d (idx %d) in NVM\n",
1709 nvm_chan[ch_idx], ch_idx))
1710 continue;
1711
1705 if (!(ch_flags & NVM_CHANNEL_VALID)) {1712 if (!(ch_flags & NVM_CHANNEL_VALID)) {
1706 iwl_nvm_print_channel_flags(dev, IWL_DL_LAR,1713 iwl_nvm_print_channel_flags(dev, IWL_DL_LAR,
1707 nvm_chan[ch_idx], ch_flags);1714 nvm_chan[ch_idx], ch_flags);
@@ -2031,7 +2038,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, · 323 unmodified lines
2031 if (empty_otp)2038 if (empty_otp)
2032 IWL_INFO(trans, "OTP is empty\n");2039 IWL_INFO(trans, "OTP is empty\n");
2033 2040
2034 nvm = kzalloc_flex(*nvm, channels, IWL_NUM_CHANNELS);2041 nvm = kzalloc_flex(*nvm, channels, IWL_NUM_CHANNELS_V2);
2035 if (!nvm) {2042 if (!nvm) {
2036 ret = -ENOMEM;2043 ret = -ENOMEM;
2037 goto out;2044 goto out;
drivers/net/wireless/intel/iwlwifi/iwl-trans.c+5−5
@@ -138,7 +138,7 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans) · 137 unmodified lines
138 IWL_RESET_MODE_FUNC_RESET,138 IWL_RESET_MODE_FUNC_RESET,
139 IWL_RESET_MODE_PROD_RESET,139 IWL_RESET_MODE_PROD_RESET,
140 };140 };
141 static const enum iwl_reset_mode escalation_list_sc[] = {141 static const enum iwl_reset_mode escalation_list_top[] = {
142 IWL_RESET_MODE_SW_RESET,142 IWL_RESET_MODE_SW_RESET,
143 IWL_RESET_MODE_REPROBE,143 IWL_RESET_MODE_REPROBE,
144 IWL_RESET_MODE_REPROBE,144 IWL_RESET_MODE_REPROBE,
@@ -159,14 +159,14 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans) · 14 unmodified lines
159 159
160 if (trans->request_top_reset) {160 if (trans->request_top_reset) {
161 trans->request_top_reset = 0;161 trans->request_top_reset = 0;
162 if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC)162 if (iwl_trans_is_top_reset_supported(trans))
163 return IWL_RESET_MODE_TOP_RESET;163 return IWL_RESET_MODE_TOP_RESET;
164 return IWL_RESET_MODE_PROD_RESET;164 return IWL_RESET_MODE_PROD_RESET;
165 }165 }
166 166
167 if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) {167 if (iwl_trans_is_top_reset_supported(trans)) {
168 escalation_list = escalation_list_sc;168 escalation_list = escalation_list_top;
169 escalation_list_size = ARRAY_SIZE(escalation_list_sc);169 escalation_list_size = ARRAY_SIZE(escalation_list_top);
170 } else {170 } else {
171 escalation_list = escalation_list_old;171 escalation_list = escalation_list_old;
172 escalation_list_size = ARRAY_SIZE(escalation_list_old);172 escalation_list_size = ARRAY_SIZE(escalation_list_old);
drivers/net/wireless/intel/iwlwifi/iwl-trans.h+19−1
@@ -1088,7 +1088,7 @@ static inline void iwl_trans_schedule_reset(struct iwl_trans *trans, · 1087 unmodified lines
1088 */1088 */
1089 trans->restart.during_reset = test_bit(STATUS_IN_SW_RESET,1089 trans->restart.during_reset = test_bit(STATUS_IN_SW_RESET,
1090 &trans->status);1090 &trans->status);
1091 queue_delayed_work(system_unbound_wq, &trans->restart.wk, 0);1091 queue_delayed_work(system_dfl_wq, &trans->restart.wk, 0);
1092}1092}
1093 1093
1094static inline void iwl_trans_fw_error(struct iwl_trans *trans,1094static inline void iwl_trans_fw_error(struct iwl_trans *trans,
@@ -1258,4 +1258,22 @@ bool iwl_trans_is_pm_supported(struct iwl_trans *trans); · 163 unmodified lines
1258 1258
1259bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans);1259bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans);
1260 1260
1261static inline bool iwl_trans_is_top_reset_supported(struct iwl_trans *trans)
1262{
1263 /* not supported before Sc family */
1264 if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)
1265 return false;
1266
1267 /* for Sc family only supported for Sc2/Sc2f */
1268 if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_SC &&
1269 CSR_HW_REV_TYPE(trans->info.hw_rev) == IWL_CFG_MAC_TYPE_SC)
1270 return false;
1271
1272 /* so far these numbers are increasing - not before Pe */
1273 if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) < IWL_CFG_RF_TYPE_PE)
1274 return false;
1275
1276 return true;
1277}
1278
1261#endif /* __iwl_trans_h__ */1279#endif /* __iwl_trans_h__ */
drivers/net/wireless/intel/iwlwifi/mld/constants.h+0−1
@@ -36,7 +36,6 @@ · 35 unmodified lines
36#define IWL_MLD_PS_HEAVY_RX_THLD_PACKETS 836#define IWL_MLD_PS_HEAVY_RX_THLD_PACKETS 8
37 37
38#define IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC 3038#define IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC 30
39#define IWL_MLD_SCAN_EXPIRE_TIME_SEC 20
40 39
41#define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ)40#define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ)
42 41
drivers/net/wireless/intel/iwlwifi/mld/fw.c+1−1
@@ -513,7 +513,7 @@ static int iwl_mld_config_fw(struct iwl_mld *mld) · 512 unmodified lines
513 return ret;513 return ret;
514 514
515 iwl_mld_init_tas(mld);515 iwl_mld_init_tas(mld);
516 iwl_mld_init_uats(mld);516 iwl_mld_init_ap_type_tables(mld);
517 517
518 return 0;518 return 0;
519}519}
drivers/net/wireless/intel/iwlwifi/mld/iface.c+17−5
@@ -61,20 +61,27 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif) · 60 unmodified lines
61static int iwl_mld_send_mac_cmd(struct iwl_mld *mld,61static int iwl_mld_send_mac_cmd(struct iwl_mld *mld,
62 struct iwl_mac_config_cmd *cmd)62 struct iwl_mac_config_cmd *cmd)
63{63{
64 u16 cmd_id = WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD);
65 int len = sizeof(*cmd);
64 int ret;66 int ret;
65 67
66 lockdep_assert_wiphy(mld->wiphy);68 lockdep_assert_wiphy(mld->wiphy);
67 69
68 ret = iwl_mld_send_cmd_pdu(mld,70 if (iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0) < 4) {
69 WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),71 if (WARN_ON(cmd->mac_type == cpu_to_le32(FW_MAC_TYPE_NAN)))
70 cmd);72 return -EINVAL;
73
74 len = sizeof(struct iwl_mac_config_cmd_v3);
75 }
76
77 ret = iwl_mld_send_cmd_pdu(mld, cmd_id, cmd, len);
71 if (ret)78 if (ret)
72 IWL_ERR(mld, "Failed to send MAC_CONFIG_CMD ret = %d\n", ret);79 IWL_ERR(mld, "Failed to send MAC_CONFIG_CMD ret = %d\n", ret);
73 80
74 return ret;81 return ret;
75}82}
76 83
77int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif)84static int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif)
78{85{
79 switch (vif->type) {86 switch (vif->type) {
80 case NL80211_IFTYPE_STATION:87 case NL80211_IFTYPE_STATION:
@@ -386,7 +393,7 @@ static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy, · 305 unmodified lines
386 iwl_mld_int_mlo_scan(mld, iwl_mld_vif_to_mac80211(mld_vif));393 iwl_mld_int_mlo_scan(mld, iwl_mld_vif_to_mac80211(mld_vif));
387}394}
388 395
389IWL_MLD_ALLOC_FN(vif, vif)396static IWL_MLD_ALLOC_FN(vif, vif)
390 397
391/* Constructor function for struct iwl_mld_vif */398/* Constructor function for struct iwl_mld_vif */
392static void399static void
@@ -397,6 +404,7 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) · 4 unmodified lines
397 lockdep_assert_wiphy(mld->wiphy);404 lockdep_assert_wiphy(mld->wiphy);
398 405
399 mld_vif->mld = mld;406 mld_vif->mld = mld;
407 mld_vif->fw_id = IWL_MLD_INVALID_FW_ID;
400 mld_vif->roc_activity = ROC_NUM_ACTIVITIES;408 mld_vif->roc_activity = ROC_NUM_ACTIVITIES;
401 409
402 if (!mld->fw_status.in_hw_restart) {410 if (!mld->fw_status.in_hw_restart) {
@@ -444,6 +452,10 @@ void iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) · 41 unmodified lines
444 452
445 lockdep_assert_wiphy(mld->wiphy);453 lockdep_assert_wiphy(mld->wiphy);
446 454
455 /* NAN interface type is not known to FW */
456 if (vif->type == NL80211_IFTYPE_NAN)
457 return;
458
447 iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE);459 iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE);
448 460
449 if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->fw_id_to_vif)))461 if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->fw_id_to_vif)))
drivers/net/wireless/intel/iwlwifi/mld/iface.h+12−3
@@ -1,6 +1,6 @@
1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2/*2/*
3 * Copyright (C) 2024-2025 Intel Corporation3 * Copyright (C) 2024-2026 Intel Corporation
4 */4 */
5#ifndef __iwl_mld_iface_h__5#ifndef __iwl_mld_iface_h__
6#define __iwl_mld_iface_h__6#define __iwl_mld_iface_h__
@@ -33,6 +33,7 @@ enum iwl_mld_cca_40mhz_wa_status { · 26 unmodified lines
33 * there is an indication that a non-BSS interface is to be added.33 * there is an indication that a non-BSS interface is to be added.
34 * @IWL_MLD_EMLSR_BLOCKED_TPT: throughput is too low to make EMLSR worthwhile34 * @IWL_MLD_EMLSR_BLOCKED_TPT: throughput is too low to make EMLSR worthwhile
35 * @IWL_MLD_EMLSR_BLOCKED_NAN: NAN is preventing EMLSR.35 * @IWL_MLD_EMLSR_BLOCKED_NAN: NAN is preventing EMLSR.
36 * @IWL_MLD_EMLSR_BLOCKED_TDLS: TDLS connection is preventing EMLSR.
36 */37 */
37enum iwl_mld_emlsr_blocked {38enum iwl_mld_emlsr_blocked {
38 IWL_MLD_EMLSR_BLOCKED_PREVENTION = 0x1,39 IWL_MLD_EMLSR_BLOCKED_PREVENTION = 0x1,
@@ -42,6 +43,7 @@ enum iwl_mld_emlsr_blocked { · 3 unmodified lines
42 IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS = 0x10,43 IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS = 0x10,
43 IWL_MLD_EMLSR_BLOCKED_TPT = 0x20,44 IWL_MLD_EMLSR_BLOCKED_TPT = 0x20,
44 IWL_MLD_EMLSR_BLOCKED_NAN = 0x40,45 IWL_MLD_EMLSR_BLOCKED_NAN = 0x40,
46 IWL_MLD_EMLSR_BLOCKED_TDLS = 0x80,
45};47};
46 48
47/**49/**
@@ -201,6 +203,15 @@ iwl_mld_vif_to_mac80211(struct iwl_mld_vif *mld_vif) · 153 unmodified lines
201 return container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);203 return container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
202}204}
203 205
206/* Call only for interfaces that were added to the driver! */
207static inline bool iwl_mld_vif_fw_id_valid(struct iwl_mld_vif *mld_vif)
208{
209 if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld_vif->mld->fw_id_to_vif)))
210 return false;
211
212 return true;
213}
214
204#define iwl_mld_link_dereference_check(mld_vif, link_id) \215#define iwl_mld_link_dereference_check(mld_vif, link_id) \
205 rcu_dereference_check((mld_vif)->link[link_id], \216 rcu_dereference_check((mld_vif)->link[link_id], \
206 lockdep_is_held(&mld_vif->mld->wiphy->mtx))217 lockdep_is_held(&mld_vif->mld->wiphy->mtx))
@@ -219,8 +230,6 @@ iwl_mld_link_from_mac80211(struct ieee80211_bss_conf *bss_conf) · 12 unmodified lines
219 return iwl_mld_link_dereference_check(mld_vif, bss_conf->link_id);230 return iwl_mld_link_dereference_check(mld_vif, bss_conf->link_id);
220}231}
221 232
222int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif);
223
224/* Cleanup function for struct iwl_mld_vif, will be called in restart */233/* Cleanup function for struct iwl_mld_vif, will be called in restart */
225void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif);234void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
226int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,235int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
drivers/net/wireless/intel/iwlwifi/mld/link.c+1−1
@@ -437,7 +437,7 @@ iwl_mld_rm_link_from_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link) · 436 unmodified lines
437 iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_REMOVE);437 iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_REMOVE);
438}438}
439 439
440IWL_MLD_ALLOC_FN(link, bss_conf)440static IWL_MLD_ALLOC_FN(link, bss_conf)
441 441
442/* Constructor function for struct iwl_mld_link */442/* Constructor function for struct iwl_mld_link */
443static int443static int
drivers/net/wireless/intel/iwlwifi/mld/link.h+2−0
@@ -40,6 +40,7 @@ struct iwl_probe_resp_data { · 39 unmodified lines
40 * @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS.40 * @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS.
41 * @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.41 * @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.
42 * @mon_sta: station used for TX injection in monitor interface.42 * @mon_sta: station used for TX injection in monitor interface.
43 * @last_cqm_rssi_event: rssi of the last cqm rssi event
43 * @average_beacon_energy: average beacon energy for beacons received during44 * @average_beacon_energy: average beacon energy for beacons received during
44 * client connections45 * client connections
45 * @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs,46 * @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs,
@@ -66,6 +67,7 @@ struct iwl_mld_link { · 20 unmodified lines
66 struct iwl_mld_int_sta bcast_sta;67 struct iwl_mld_int_sta bcast_sta;
67 struct iwl_mld_int_sta mcast_sta;68 struct iwl_mld_int_sta mcast_sta;
68 struct iwl_mld_int_sta mon_sta;69 struct iwl_mld_int_sta mon_sta;
70 int last_cqm_rssi_event;
69 71
70 /* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */72 /* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */
71 struct ieee80211_key_conf *ap_early_keys[6];73 struct ieee80211_key_conf *ap_early_keys[6];
drivers/net/wireless/intel/iwlwifi/mld/low_latency.c+9−4
@@ -1,6 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/*2/*
3 * Copyright (C) 2024-2025 Intel Corporation3 * Copyright (C) 2024-2026 Intel Corporation
4 */4 */
5#include "mld.h"5#include "mld.h"
6#include "iface.h"6#include "iface.h"
@@ -77,9 +77,12 @@ static void iwl_mld_low_latency_iter(void *_data, u8 *mac, · 70 unmodified lines
77 bool prev = mld_vif->low_latency_causes & LOW_LATENCY_TRAFFIC;77 bool prev = mld_vif->low_latency_causes & LOW_LATENCY_TRAFFIC;
78 bool low_latency;78 bool low_latency;
79 79
80 if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->low_latency.result)))80 if (!iwl_mld_vif_fw_id_valid(mld_vif))
81 return;81 return;
82 82
83 BUILD_BUG_ON(ARRAY_SIZE(mld->fw_id_to_vif) !=
84 ARRAY_SIZE(mld->low_latency.result));
85
83 low_latency = mld->low_latency.result[mld_vif->fw_id];86 low_latency = mld->low_latency.result[mld_vif->fw_id];
84 87
85 if (prev != low_latency)88 if (prev != low_latency)
@@ -272,8 +275,10 @@ void iwl_mld_low_latency_update_counters(struct iwl_mld *mld, · 186 unmodified lines
272 if (WARN_ON_ONCE(!mld->low_latency.pkts_counters))275 if (WARN_ON_ONCE(!mld->low_latency.pkts_counters))
273 return;276 return;
274 277
275 if (WARN_ON_ONCE(fw_id >= ARRAY_SIZE(counters->vo_vi) ||278 if (!iwl_mld_vif_fw_id_valid(mld_vif))
276 queue >= mld->trans->info.num_rxqs))279 return;
280
281 if (WARN_ON_ONCE(queue >= mld->trans->info.num_rxqs))
277 return;282 return;
278 283
279 if (mld->low_latency.stopped)284 if (mld->low_latency.stopped)
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c+48−4
@@ -754,6 +754,30 @@ void iwl_mld_mac80211_remove_interface(struct ieee80211_hw *hw, · 753 unmodified lines
754 mld->monitor.phy.valid = false;754 mld->monitor.phy.valid = false;
755}755}
756 756
757static
758int iwl_mld_mac80211_change_interface(struct ieee80211_hw *hw,
759 struct ieee80211_vif *vif,
760 enum nl80211_iftype new_type, bool p2p)
761{
762 enum nl80211_iftype old_type = vif->type;
763 bool old_p2p = vif->p2p;
764 int ret;
765
766 iwl_mld_mac80211_remove_interface(hw, vif);
767
768 /* set the new type for adding it cleanly */
769 vif->type = new_type;
770 vif->p2p = p2p;
771
772 ret = iwl_mld_mac80211_add_interface(hw, vif);
773
774 /* restore for mac80211, it will change it again */
775 vif->type = old_type;
776 vif->p2p = old_p2p;
777
778 return ret;
779}
780
757struct iwl_mld_mc_iter_data {781struct iwl_mld_mc_iter_data {
758 struct iwl_mld *mld;782 struct iwl_mld *mld;
759 int port_id;783 int port_id;
@@ -1124,6 +1148,8 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw, · 364 unmodified lines
1124 1148
1125 /* Now activate the link */1149 /* Now activate the link */
1126 if (iwl_mld_can_activate_link(mld, vif, link)) {1150 if (iwl_mld_can_activate_link(mld, vif, link)) {
1151 iwl_mld_tlc_update_phy(mld, vif, link);
1152
1127 ret = iwl_mld_activate_link(mld, link);1153 ret = iwl_mld_activate_link(mld, link);
1128 if (ret)1154 if (ret)
1129 goto err;1155 goto err;
@@ -1185,6 +1211,8 @@ void iwl_mld_unassign_vif_chanctx(struct ieee80211_hw *hw, · 55 unmodified lines
1185 1211
1186 RCU_INIT_POINTER(mld_link->chan_ctx, NULL);1212 RCU_INIT_POINTER(mld_link->chan_ctx, NULL);
1187 1213
1214 iwl_mld_tlc_update_phy(mld, vif, link);
1215
1188 /* in the non-MLO case, remove/re-add the link to clean up FW state.1216 /* in the non-MLO case, remove/re-add the link to clean up FW state.
1189 * In MLO, it'll be done in drv_change_vif_link1217 * In MLO, it'll be done in drv_change_vif_link
1190 */1218 */
@@ -1727,14 +1755,23 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld, · 536 unmodified lines
1727 return -EBUSY;1755 return -EBUSY;
1728 }1756 }
1729 1757
1730 ret = iwl_mld_add_sta(mld, sta, vif, STATION_TYPE_PEER);1758 ret = iwl_mld_add_sta(mld, sta, vif);
1731 if (ret)1759 if (ret)
1732 return ret;1760 return ret;
1733 1761
1734 /* just added first TDLS STA, so disable PM */1762 /* just added first TDLS STA, so disable PM and block EMLSR */
1735 if (sta->tdls && tdls_count == 0)1763 if (sta->tdls && tdls_count == 0) {
1736 iwl_mld_update_mac_power(mld, vif, false);1764 iwl_mld_update_mac_power(mld, vif, false);
1737 1765
1766 /* TDLS requires single-link operation with
1767 * direct peer communication.
1768 * Block and exit EMLSR when TDLS is established.
1769 */
1770 iwl_mld_block_emlsr(mld, vif,
1771 IWL_MLD_EMLSR_BLOCKED_TDLS,
1772 iwl_mld_get_primary_link(vif));
1773 }
1774
1738 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)1775 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
1739 mld_vif->ap_sta = sta;1776 mld_vif->ap_sta = sta;
1740 1777
@@ -1870,8 +1907,14 @@ static int iwl_mld_move_sta_state_down(struct iwl_mld *mld, · 129 unmodified lines
1870 iwl_mld_remove_sta(mld, sta);1907 iwl_mld_remove_sta(mld, sta);
1871 1908
1872 if (sta->tdls && iwl_mld_tdls_sta_count(mld) == 0) {1909 if (sta->tdls && iwl_mld_tdls_sta_count(mld) == 0) {
1873 /* just removed last TDLS STA, so enable PM */1910 /* just removed last TDLS STA, so enable PM
1911 * and unblock EMLSR
1912 */
1874 iwl_mld_update_mac_power(mld, vif, false);1913 iwl_mld_update_mac_power(mld, vif, false);
1914
1915 /* Unblock EMLSR when TDLS connection is torn down */
1916 iwl_mld_unblock_emlsr(mld, vif,
1917 IWL_MLD_EMLSR_BLOCKED_TDLS);
1875 }1918 }
1876 } else {1919 } else {
1877 return -EINVAL;1920 return -EINVAL;
@@ -2716,6 +2759,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = { · 838 unmodified lines
2716 .get_antenna = iwl_mld_get_antenna,2759 .get_antenna = iwl_mld_get_antenna,
2717 .set_antenna = iwl_mld_set_antenna,2760 .set_antenna = iwl_mld_set_antenna,
2718 .add_interface = iwl_mld_mac80211_add_interface,2761 .add_interface = iwl_mld_mac80211_add_interface,
2762 .change_interface = iwl_mld_mac80211_change_interface,
2719 .remove_interface = iwl_mld_mac80211_remove_interface,2763 .remove_interface = iwl_mld_mac80211_remove_interface,
2720 .conf_tx = iwl_mld_mac80211_conf_tx,2764 .conf_tx = iwl_mld_mac80211_conf_tx,
2721 .prepare_multicast = iwl_mld_mac80211_prepare_multicast,2765 .prepare_multicast = iwl_mld_mac80211_prepare_multicast,
drivers/net/wireless/intel/iwlwifi/mld/mld.h+3−3
@@ -205,7 +205,7 @@ · 204 unmodified lines
205struct iwl_mld {205struct iwl_mld {
206 /* Add here fields that need clean up on restart */206 /* Add here fields that need clean up on restart */
207 struct_group(zeroed_on_hw_restart,207 struct_group(zeroed_on_hw_restart,
208 struct ieee80211_bss_conf __rcu *fw_id_to_bss_conf[IWL_FW_MAX_LINK_ID + 1];208 struct ieee80211_bss_conf __rcu *fw_id_to_bss_conf[IWL_FW_MAX_LINKS];
209 struct ieee80211_vif __rcu *fw_id_to_vif[NUM_MAC_INDEX_DRIVER];209 struct ieee80211_vif __rcu *fw_id_to_vif[NUM_MAC_INDEX_DRIVER];
210 struct ieee80211_txq __rcu *fw_id_to_txq[IWL_MAX_TVQM_QUEUES];210 struct ieee80211_txq __rcu *fw_id_to_txq[IWL_MAX_TVQM_QUEUES];
211 u8 used_phy_ids: NUM_PHY_CTX;211 u8 used_phy_ids: NUM_PHY_CTX;
@@ -530,9 +530,9 @@ void iwl_construct_mld(struct iwl_mld *mld, struct iwl_trans *trans, · 318 unmodified lines
530#define IWL_MLD_INVALID_FW_ID 0xff530#define IWL_MLD_INVALID_FW_ID 0xff
531 531
532#define IWL_MLD_ALLOC_FN(_type, _mac80211_type) \532#define IWL_MLD_ALLOC_FN(_type, _mac80211_type) \
533static int \533int \
534iwl_mld_allocate_##_type##_fw_id(struct iwl_mld *mld, \534iwl_mld_allocate_##_type##_fw_id(struct iwl_mld *mld, \
535 u8 *fw_id, \535 u8 *fw_id, \
536 struct ieee80211_##_mac80211_type *mac80211_ptr) \536 struct ieee80211_##_mac80211_type *mac80211_ptr) \
537{ \537{ \
538 u8 rand = IWL_MLD_DIS_RANDOM_FW_ID ? 0 : get_random_u8(); \538 u8 rand = IWL_MLD_DIS_RANDOM_FW_ID ? 0 : get_random_u8(); \
drivers/net/wireless/intel/iwlwifi/mld/mlo.c+2−2
@@ -13,7 +13,8 @@ · 12 unmodified lines
13 HOW(NON_BSS) \13 HOW(NON_BSS) \
14 HOW(TMP_NON_BSS) \14 HOW(TMP_NON_BSS) \
15 HOW(TPT) \15 HOW(TPT) \
16 HOW(NAN)16 HOW(NAN) \
17 HOW(TDLS)
17 18
18static const char *19static const char *
19iwl_mld_get_emlsr_blocked_string(enum iwl_mld_emlsr_blocked blocked)20iwl_mld_get_emlsr_blocked_string(enum iwl_mld_emlsr_blocked blocked)
@@ -110,7 +111,6 @@ void iwl_mld_emlsr_tmp_non_bss_done_wk(struct wiphy *wiphy, · 90 unmodified lines
110}111}
111 112
112#define IWL_MLD_TRIGGER_LINK_SEL_TIME (HZ * IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC)113#define IWL_MLD_TRIGGER_LINK_SEL_TIME (HZ * IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC)
113#define IWL_MLD_SCAN_EXPIRE_TIME (HZ * IWL_MLD_SCAN_EXPIRE_TIME_SEC)
114 114
115/* Exit reasons that can cause longer EMLSR prevention */115/* Exit reasons that can cause longer EMLSR prevention */
116#define IWL_MLD_PREVENT_EMLSR_REASONS (IWL_MLD_EMLSR_EXIT_MISSED_BEACON | \116#define IWL_MLD_PREVENT_EMLSR_REASONS (IWL_MLD_EMLSR_EXIT_MISSED_BEACON | \
drivers/net/wireless/intel/iwlwifi/mld/nan.h+4−1
@@ -2,7 +2,8 @@ · 1 unmodified line
2/*2/*
3 * Copyright (C) 2025 Intel Corporation3 * Copyright (C) 2025 Intel Corporation
4 */4 */
5 5#ifndef __iwl_mld_nan_h__
6#define __iwl_mld_nan_h__
6#include <net/cfg80211.h>7#include <net/cfg80211.h>
7#include <linux/etherdevice.h>8#include <linux/etherdevice.h>
8 9
@@ -26,3 +27,5 @@ bool iwl_mld_cancel_nan_cluster_notif(struct iwl_mld *mld, · 17 unmodified lines
26bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld,27bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld,
27 struct iwl_rx_packet *pkt,28 struct iwl_rx_packet *pkt,
28 u32 obj_id);29 u32 obj_id);
30
31#endif /* __iwl_mld_nan_h__ */
drivers/net/wireless/intel/iwlwifi/mld/phy.h+2−2
@@ -32,9 +32,9 @@ struct iwl_mld_phy { · 31 unmodified lines
32};32};
33 33
34static inline struct iwl_mld_phy *34static inline struct iwl_mld_phy *
35iwl_mld_phy_from_mac80211(struct ieee80211_chanctx_conf *channel)35iwl_mld_phy_from_mac80211(struct ieee80211_chanctx_conf *chanctx)
36{36{
37 return (void *)channel->drv_priv;37 return (void *)chanctx->drv_priv;
38}38}
39 39
40/* Cleanup function for struct iwl_mld_phy, will be called in restart */40/* Cleanup function for struct iwl_mld_phy, will be called in restart */
drivers/net/wireless/intel/iwlwifi/mld/power.c+4−1
@@ -405,7 +405,10 @@ int iwl_mld_set_tx_power(struct iwl_mld *mld, · 404 unmodified lines
405 .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK),405 .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK),
406 .common.pwr_restriction = cpu_to_le16(u_tx_power),406 .common.pwr_restriction = cpu_to_le16(u_tx_power),
407 };407 };
408 int len = sizeof(cmd.common) + sizeof(cmd.v10);408 int len = sizeof(cmd.common) + sizeof(cmd.v11);
409
410 if (iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 10) == 10)
411 len = sizeof(cmd.common) + sizeof(cmd.v10);
409 412
410 if (WARN_ON(!mld_link))413 if (WARN_ON(!mld_link))
411 return -ENODEV;414 return -ENODEV;
drivers/net/wireless/intel/iwlwifi/mld/ptp.c+3−1
@@ -301,10 +301,12 @@ void iwl_mld_ptp_init(struct iwl_mld *mld) · 300 unmodified lines
301 mld->ptp_data.ptp_clock =301 mld->ptp_data.ptp_clock =
302 ptp_clock_register(&mld->ptp_data.ptp_clock_info, mld->dev);302 ptp_clock_register(&mld->ptp_data.ptp_clock_info, mld->dev);
303 303
304 if (IS_ERR_OR_NULL(mld->ptp_data.ptp_clock)) {304 if (IS_ERR(mld->ptp_data.ptp_clock)) {
305 IWL_ERR(mld, "Failed to register PHC clock (%ld)\n",305 IWL_ERR(mld, "Failed to register PHC clock (%ld)\n",
306 PTR_ERR(mld->ptp_data.ptp_clock));306 PTR_ERR(mld->ptp_data.ptp_clock));
307 mld->ptp_data.ptp_clock = NULL;307 mld->ptp_data.ptp_clock = NULL;
308 } else if (!mld->ptp_data.ptp_clock) {
309 IWL_DEBUG_INFO(mld, "PTP module unavailable on this kernel\n");
308 } else {310 } else {
309 IWL_DEBUG_INFO(mld, "Registered PHC clock: %s, with index: %d\n",311 IWL_DEBUG_INFO(mld, "Registered PHC clock: %s, with index: %d\n",
310 mld->ptp_data.ptp_clock_info.name,312 mld->ptp_data.ptp_clock_info.name,
drivers/net/wireless/intel/iwlwifi/mld/regulatory.c+148−30
@@ -64,6 +64,7 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld) · 63 unmodified lines
64 }64 }
65 65
66 iwl_uefi_get_uats_table(mld->trans, &mld->fwrt);66 iwl_uefi_get_uats_table(mld->trans, &mld->fwrt);
67 iwl_uefi_get_uneb_table(mld->trans, &mld->fwrt);
67 68
68 iwl_bios_get_phy_filters(&mld->fwrt);69 iwl_bios_get_phy_filters(&mld->fwrt);
69}70}
@@ -72,16 +73,36 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld) · 2 unmodified lines
72{73{
73 u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD);74 u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD);
74 /* Only set to South Korea if the table revision is 1 */75 /* Only set to South Korea if the table revision is 1 */
75 __le32 sk = cpu_to_le32(mld->fwrt.geo_rev == 1 ? 1 : 0);76 u8 sk = mld->fwrt.geo_rev == 1 ? 1 : 0;
76 union iwl_geo_tx_power_profiles_cmd cmd = {77 union iwl_geo_tx_power_profiles_cmd cmd = {
77 .v5.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),78 .v5.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
78 .v5.table_revision = sk,
79 };79 };
80 u32 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0);
81 int n_subbands;
82 int cmd_size;
80 int ret;83 int ret;
81 84
82 ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v5.table[0][0],85 switch (cmd_ver) {
83 ARRAY_SIZE(cmd.v5.table[0]),86 case 5:
84 BIOS_GEO_MAX_PROFILE_NUM);87 n_subbands = ARRAY_SIZE(cmd.v5.table[0]);
88 cmd.v5.table_revision = cpu_to_le32(sk);
89 cmd_size = sizeof(cmd.v5);
90 break;
91 case 6:
92 n_subbands = ARRAY_SIZE(cmd.v6.table[0]);
93 cmd.v6.bios_hdr.table_revision = mld->fwrt.geo_rev;
94 cmd.v6.bios_hdr.table_source = mld->fwrt.geo_bios_source;
95 cmd_size = sizeof(cmd.v6);
96 break;
97 default:
98 WARN(false, "unsupported version: %d", cmd_ver);
99 return -EINVAL;
100 }
101
102 BUILD_BUG_ON(offsetof(typeof(cmd), v6.table) !=
103 offsetof(typeof(cmd), v5.table));
104 ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v6.table[0][0],
105 n_subbands, BIOS_GEO_MAX_PROFILE_NUM);
85 106
86 /* It is a valid scenario to not support SAR, or miss wgds table,107 /* It is a valid scenario to not support SAR, or miss wgds table,
87 * but in that case there is no need to send the command.108 * but in that case there is no need to send the command.
@@ -89,28 +110,48 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld) · 1 unmodified line
89 if (ret)110 if (ret)
90 return 0;111 return 0;
91 112
92 return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, sizeof(cmd.v5));113 return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, cmd_size);
93}114}
94 115
95int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)116int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
96{117{
97 u32 cmd_id = REDUCE_TX_POWER_CMD;
98 struct iwl_dev_tx_power_cmd cmd = {118 struct iwl_dev_tx_power_cmd cmd = {
99 .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),119 .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
100 .v10.flags = cpu_to_le32(mld->fwrt.reduced_power_flags),
101 };120 };
121 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, REDUCE_TX_POWER_CMD, 10);
122 int num_subbands;
123 int cmd_size;
102 int ret;124 int ret;
103 125
126 switch (cmd_ver) {
127 case 10:
128 cmd.v10.flags = cpu_to_le32(mld->fwrt.reduced_power_flags);
129 cmd_size = sizeof(cmd.common) + sizeof(cmd.v10);
130 num_subbands = IWL_NUM_SUB_BANDS_V2;
131 break;
132 case 11:
133 cmd.v11.flags = cpu_to_le32(mld->fwrt.reduced_power_flags);
134 cmd_size = sizeof(cmd.common) + sizeof(cmd.v11);
135 num_subbands = IWL_NUM_SUB_BANDS_V3;
136 break;
137 default:
138 WARN_ONCE(1, "Bad version for REDUCE_TX_POWER_CMD: %d\n",
139 cmd_ver);
140 return -EOPNOTSUPP;
141 }
142
104 /* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */143 /* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */
105 ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v10.per_chain[0][0][0],144 /* v10 and v11 have the same position for per_chain */
106 IWL_NUM_CHAIN_TABLES, IWL_NUM_SUB_BANDS_V2,145 BUILD_BUG_ON(offsetof(typeof(cmd), v11.per_chain) !=
146 offsetof(typeof(cmd), v10.per_chain));
147 ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v11.per_chain[0][0][0],
148 IWL_NUM_CHAIN_TABLES, num_subbands,
107 prof_a, prof_b);149 prof_a, prof_b);
108 /* return on error or if the profile is disabled (positive number) */150 /* return on error or if the profile is disabled (positive number) */
109 if (ret)151 if (ret)
110 return ret;152 return ret;
111 153
112 return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd,154 return iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, &cmd, cmd_size);
113 sizeof(cmd.common) + sizeof(cmd.v10));
114}155}
115 156
116int iwl_mld_init_sar(struct iwl_mld *mld)157int iwl_mld_init_sar(struct iwl_mld *mld)
@@ -165,30 +206,86 @@ static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld) · 48 unmodified lines
165{206{
166 struct iwl_fw_runtime *fwrt = &mld->fwrt;207 struct iwl_fw_runtime *fwrt = &mld->fwrt;
167 union iwl_ppag_table_cmd cmd = {208 union iwl_ppag_table_cmd cmd = {
168 .v7.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,209 /* v7 and v8 have the same layout for the ppag_config_info */
169 .v7.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,210 .v8.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,
170 .v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),211 .v8.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
212 .v8.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
171 };213 };
214 u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD);
215 int cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 1);
216 int cmd_len = sizeof(cmd.v8);
217 u8 cmd_bios_rev;
172 int ret;218 int ret;
173 219
220 BUILD_BUG_ON(offsetof(typeof(cmd), v8.ppag_config_info.hdr) !=
221 offsetof(typeof(cmd), v7.ppag_config_info.hdr));
222 BUILD_BUG_ON(offsetof(typeof(cmd), v8.gain) !=
223 offsetof(typeof(cmd), v7.gain));
224
225 BUILD_BUG_ON(ARRAY_SIZE(cmd.v7.gain) > ARRAY_SIZE(fwrt->ppag_chains));
226 BUILD_BUG_ON(ARRAY_SIZE(cmd.v7.gain[0]) >
227 ARRAY_SIZE(fwrt->ppag_chains[0].subbands));
228 BUILD_BUG_ON(ARRAY_SIZE(cmd.v8.gain) > ARRAY_SIZE(fwrt->ppag_chains));
229 BUILD_BUG_ON(ARRAY_SIZE(cmd.v8.gain[0]) >
230 ARRAY_SIZE(fwrt->ppag_chains[0].subbands));
231
174 IWL_DEBUG_RADIO(fwrt,232 IWL_DEBUG_RADIO(fwrt,
175 "PPAG MODE bits going to be sent: %d\n",233 "PPAG MODE bits going to be sent: %d\n",
176 fwrt->ppag_flags);234 fwrt->ppag_flags);
177 235
178 for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) {236 /* Since ver 7 will be deprecated at some point, don't bother making
179 for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) {237 * this code generic for both ver 7 and ver 8: duplicate the code.
180 cmd.v7.gain[chain][subband] =238 */
181 fwrt->ppag_chains[chain].subbands[subband];239 if (cmd_ver == 7) {
182 IWL_DEBUG_RADIO(fwrt,240 for (int chain = 0; chain < ARRAY_SIZE(cmd.v7.gain); chain++) {
183 "PPAG table: chain[%d] band[%d]: gain = %d\n",241 for (int subband = 0;
184 chain, subband, cmd.v7.gain[chain][subband]);242 subband < ARRAY_SIZE(cmd.v7.gain[0]);
243 subband++) {
244 cmd.v7.gain[chain][subband] =
245 fwrt->ppag_chains[chain].subbands[subband];
246 IWL_DEBUG_RADIO(fwrt,
247 "PPAG table: chain[%d] band[%d]: gain = %d\n",
248 chain, subband,
249 cmd.v7.gain[chain][subband]);
250 }
251 }
252 cmd_len = sizeof(cmd.v7);
253 cmd_bios_rev =
254 iwl_fw_lookup_cmd_bios_supported_revision(fwrt->fw,
255 fwrt->ppag_bios_source,
256 cmd_id, 4);
257 } else if (cmd_ver == 8) {
258 for (int chain = 0; chain < ARRAY_SIZE(cmd.v8.gain); chain++) {
259 for (int subband = 0;
260 subband < ARRAY_SIZE(cmd.v8.gain[0]);
261 subband++) {
262 cmd.v8.gain[chain][subband] =
263 fwrt->ppag_chains[chain].subbands[subband];
264 IWL_DEBUG_RADIO(fwrt,
265 "PPAG table: chain[%d] band[%d]: gain = %d\n",
266 chain, subband,
267 cmd.v8.gain[chain][subband]);
268 }
185 }269 }
270 cmd_bios_rev =
271 iwl_fw_lookup_cmd_bios_supported_revision(fwrt->fw,
272 fwrt->ppag_bios_source,
273 cmd_id, 5);
274 } else {
275 WARN(1, "Bad version for PER_PLATFORM_ANT_GAIN_CMD %d\n",
276 cmd_ver);
277 return -EINVAL;
278 }
279
280 if (cmd_bios_rev < fwrt->ppag_bios_rev) {
281 IWL_ERR(mld,
282 "BIOS revision compatibility check failed - Supported: %d, Current: %d\n",
283 cmd_bios_rev, fwrt->ppag_bios_rev);
284 return 0;
186 }285 }
187 286
188 IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");287 IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
189 ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP,288 ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, cmd_len);
190 PER_PLATFORM_ANT_GAIN_CMD),
191 &cmd, sizeof(cmd.v7));
192 if (ret < 0)289 if (ret < 0)
193 IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",290 IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
194 ret);291 ret);
@@ -352,21 +449,42 @@ void iwl_mld_configure_lari(struct iwl_mld *mld) · 157 unmodified lines
352 ret);449 ret);
353}450}
354 451
355void iwl_mld_init_uats(struct iwl_mld *mld)452void iwl_mld_init_ap_type_tables(struct iwl_mld *mld)
356{453{
357 int ret;454 int ret;
358 struct iwl_host_cmd cmd = {455 struct iwl_host_cmd cmd = {
359 .id = WIDE_ID(REGULATORY_AND_NVM_GROUP,456 .id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
360 MCC_ALLOWED_AP_TYPE_CMD),457 MCC_ALLOWED_AP_TYPE_CMD),
361 .data[0] = &mld->fwrt.uats_table,458 .data[0] = &mld->fwrt.ap_type_cmd,
362 .len[0] = sizeof(mld->fwrt.uats_table),459 .len[0] = sizeof(mld->fwrt.ap_type_cmd),
363 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,460 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
364 };461 };
365 462
366 if (!mld->fwrt.uats_valid)463 if (!mld->fwrt.ap_type_cmd_valid)
367 return;464 return;
368 465
369 ret = iwl_mld_send_cmd(mld, &cmd);466 if (iwl_fw_lookup_cmd_ver(mld->fw, cmd.id, 1) == 1) {
467 struct iwl_mcc_allowed_ap_type_cmd_v1 *cmd_v1 =
468 kzalloc(sizeof(*cmd_v1), GFP_KERNEL);
469
470 if (!cmd_v1)
471 return;
472
473 BUILD_BUG_ON(sizeof(mld->fwrt.ap_type_cmd.mcc_to_ap_type_map) !=
474 sizeof(cmd_v1->mcc_to_ap_type_map));
475
476 memcpy(cmd_v1->mcc_to_ap_type_map,
477 mld->fwrt.ap_type_cmd.mcc_to_ap_type_map,
478 sizeof(mld->fwrt.ap_type_cmd.mcc_to_ap_type_map));
479
480 cmd.data[0] = cmd_v1;
481 cmd.len[0] = sizeof(*cmd_v1);
482 ret = iwl_mld_send_cmd(mld, &cmd);
483 kfree(cmd_v1);
484 } else {
485 ret = iwl_mld_send_cmd(mld, &cmd);
486 }
487
370 if (ret)488 if (ret)
371 IWL_ERR(mld, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",489 IWL_ERR(mld, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",
372 ret);490 ret);
drivers/net/wireless/intel/iwlwifi/mld/regulatory.h+1−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
9 9
10void iwl_mld_get_bios_tables(struct iwl_mld *mld);10void iwl_mld_get_bios_tables(struct iwl_mld *mld);
11void iwl_mld_configure_lari(struct iwl_mld *mld);11void iwl_mld_configure_lari(struct iwl_mld *mld);
12void iwl_mld_init_uats(struct iwl_mld *mld);12void iwl_mld_init_ap_type_tables(struct iwl_mld *mld);
13void iwl_mld_init_tas(struct iwl_mld *mld);13void iwl_mld_init_tas(struct iwl_mld *mld);
14 14
15int iwl_mld_init_ppag(struct iwl_mld *mld);15int iwl_mld_init_ppag(struct iwl_mld *mld);
drivers/net/wireless/intel/iwlwifi/mld/rx.c+14−11
@@ -1,6 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/*2/*
3 * Copyright (C) 2024-2025 Intel Corporation3 * Copyright (C) 2024-2026 Intel Corporation
4 */4 */
5 5
6#include <net/mac80211.h>6#include <net/mac80211.h>
@@ -791,6 +791,9 @@ static void * · 784 unmodified lines
791iwl_mld_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len)791iwl_mld_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len)
792{792{
793 struct ieee80211_radiotap_tlv *tlv;793 struct ieee80211_radiotap_tlv *tlv;
794 struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
795
796 rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
794 797
795 tlv = skb_put(skb, sizeof(*tlv));798 tlv = skb_put(skb, sizeof(*tlv));
796 tlv->type = cpu_to_le16(type);799 tlv->type = cpu_to_le16(type);
@@ -1234,8 +1237,6 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb, · 437 unmodified lines
1234 1237
1235 eht = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);1238 eht = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);
1236 1239
1237 rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
1238
1239 switch (u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK)) {1240 switch (u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK)) {
1240 case 0:1241 case 0:
1241 if (he_type == RATE_MCS_HE_TYPE_TRIG) {1242 if (he_type == RATE_MCS_HE_TYPE_TRIG) {
@@ -1329,7 +1330,6 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb, · 87 unmodified lines
1329static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld,1330static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld,
1330 struct sk_buff *skb)1331 struct sk_buff *skb)
1331{1332{
1332 struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
1333 struct ieee80211_radiotap_vendor_content *radiotap;1333 struct ieee80211_radiotap_vendor_content *radiotap;
1334 const u16 vendor_data_len = sizeof(mld->monitor.cur_aid);1334 const u16 vendor_data_len = sizeof(mld->monitor.cur_aid);
1335 1335
@@ -1353,8 +1353,6 @@ static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld, · 17 unmodified lines
1353 /* fill the data now */1353 /* fill the data now */
1354 memcpy(radiotap->data, &mld->monitor.cur_aid,1354 memcpy(radiotap->data, &mld->monitor.cur_aid,
1355 sizeof(mld->monitor.cur_aid));1355 sizeof(mld->monitor.cur_aid));
1356
1357 rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
1358}1356}
1359#endif1357#endif
1360 1358
@@ -1362,7 +1360,6 @@ static void iwl_mld_add_rtap_sniffer_phy_data(struct iwl_mld *mld, · 1 unmodified line
1362 struct sk_buff *skb,1360 struct sk_buff *skb,
1363 struct iwl_rx_phy_air_sniffer_ntfy *ntfy)1361 struct iwl_rx_phy_air_sniffer_ntfy *ntfy)
1364{1362{
1365 struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
1366 struct ieee80211_radiotap_vendor_content *radiotap;1363 struct ieee80211_radiotap_vendor_content *radiotap;
1367 const u16 vendor_data_len = sizeof(*ntfy);1364 const u16 vendor_data_len = sizeof(*ntfy);
1368 1365
@@ -1382,8 +1379,6 @@ static void iwl_mld_add_rtap_sniffer_phy_data(struct iwl_mld *mld, · 13 unmodified lines
1382 1379
1383 /* fill the data now */1380 /* fill the data now */
1384 memcpy(radiotap->data, ntfy, vendor_data_len);1381 memcpy(radiotap->data, ntfy, vendor_data_len);
1385
1386 rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
1387}1382}
1388 1383
1389static void1384static void
@@ -1407,6 +1402,7 @@ static void iwl_mld_set_rx_rate(struct iwl_mld *mld, · 17 unmodified lines
1407 u32 rate_n_flags = phy_data->rate_n_flags;1402 u32 rate_n_flags = phy_data->rate_n_flags;
1408 u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);1403 u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);
1409 u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;1404 u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
1405 u32 he_type = u32_get_bits(rate_n_flags, RATE_MCS_HE_TYPE_MSK);
1410 bool is_sgi = rate_n_flags & RATE_MCS_SGI_MSK;1406 bool is_sgi = rate_n_flags & RATE_MCS_SGI_MSK;
1411 1407
1412 /* bandwidth may be overridden to RU by PHY ntfy */1408 /* bandwidth may be overridden to RU by PHY ntfy */
@@ -1481,6 +1477,12 @@ static void iwl_mld_set_rx_rate(struct iwl_mld *mld, · 68 unmodified lines
1481 rx_status->encoding = RX_ENC_EHT;1477 rx_status->encoding = RX_ENC_EHT;
1482 iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);1478 iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);
1483 break;1479 break;
1480 case RATE_MCS_MOD_TYPE_UHR:
1481 rx_status->encoding = RX_ENC_UHR;
1482 iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);
1483 if (he_type == RATE_MCS_HE_TYPE_UHR_ELR)
1484 rx_status->uhr.elr = 1;
1485 break;
1484 default:1486 default:
1485 WARN_ON_ONCE(1);1487 WARN_ON_ONCE(1);
1486 }1488 }
@@ -2204,8 +2206,9 @@ void iwl_mld_sync_rx_queues(struct iwl_mld *mld, · 717 unmodified lines
2204 ret = wait_event_timeout(mld->rxq_sync.waitq,2206 ret = wait_event_timeout(mld->rxq_sync.waitq,
2205 READ_ONCE(mld->rxq_sync.state) == 0,2207 READ_ONCE(mld->rxq_sync.state) == 0,
2206 SYNC_RX_QUEUE_TIMEOUT);2208 SYNC_RX_QUEUE_TIMEOUT);
2207 WARN_ONCE(!ret, "RXQ sync failed: state=0x%lx, cookie=%d\n",2209 IWL_FW_CHECK(mld, !ret,
2208 mld->rxq_sync.state, mld->rxq_sync.cookie);2210 "RXQ sync failed: state=0x%lx, cookie=%d\n",
2211 mld->rxq_sync.state, mld->rxq_sync.cookie);
2209 2212
2210out:2213out:
2211 mld->rxq_sync.state = 0;2214 mld->rxq_sync.state = 0;
drivers/net/wireless/intel/iwlwifi/mld/scan.c+169−55
@@ -47,8 +47,6 @@ · 46 unmodified lines
47/* adaptive dwell number of APs override mask for social channels */47/* adaptive dwell number of APs override mask for social channels */
48#define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS_BIT BIT(21)48#define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS_BIT BIT(21)
49 49
50#define SCAN_TIMEOUT_MSEC (30000 * HZ)
51
52/* minimal number of 2GHz and 5GHz channels in the regular scan request */50/* minimal number of 2GHz and 5GHz channels in the regular scan request */
53#define IWL_MLD_6GHZ_PASSIVE_SCAN_MIN_CHANS 451#define IWL_MLD_6GHZ_PASSIVE_SCAN_MIN_CHANS 4
54 52
@@ -116,6 +114,13 @@ struct iwl_mld_scan_params { · 61 unmodified lines
116 u8 bssid[ETH_ALEN] __aligned(2);114 u8 bssid[ETH_ALEN] __aligned(2);
117};115};
118 116
117struct iwl_scan_req_params_ptrs {
118 struct iwl_scan_general_params_v11 *general_params;
119 struct iwl_scan_channel_params_v8 *channel_params;
120 struct iwl_scan_periodic_parms_v1 *periodic_params;
121 struct iwl_scan_probe_params_v4 *probe_params;
122};
123
119struct iwl_mld_scan_respect_p2p_go_iter_data {124struct iwl_mld_scan_respect_p2p_go_iter_data {
120 struct ieee80211_vif *current_vif;125 struct ieee80211_vif *current_vif;
121 bool p2p_go;126 bool p2p_go;
@@ -512,9 +517,10 @@ iwl_mld_scan_get_cmd_gen_flags2(struct iwl_mld *mld, · 390 unmodified lines
512 517
513static void518static void
514iwl_mld_scan_cmd_set_dwell(struct iwl_mld *mld,519iwl_mld_scan_cmd_set_dwell(struct iwl_mld *mld,
515 struct iwl_scan_general_params_v11 *gp,520 struct iwl_mld_scan_params *params,
516 struct iwl_mld_scan_params *params)521 struct iwl_scan_req_params_ptrs *scan_ptrs)
517{522{
523 struct iwl_scan_general_params_v11 *gp = scan_ptrs->general_params;
518 const struct iwl_mld_scan_timing_params *timing =524 const struct iwl_mld_scan_timing_params *timing =
519 &scan_timing[params->type];525 &scan_timing[params->type];
520 526
@@ -551,9 +557,10 @@ static void · 30 unmodified lines
551iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld,557iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld,
552 struct iwl_mld_scan_params *params,558 struct iwl_mld_scan_params *params,
553 struct ieee80211_vif *vif,559 struct ieee80211_vif *vif,
554 struct iwl_scan_general_params_v11 *gp,560 struct iwl_scan_req_params_ptrs *scan_ptrs,
555 enum iwl_mld_scan_status scan_status)561 enum iwl_mld_scan_status scan_status)
556{562{
563 struct iwl_scan_general_params_v11 *gp = scan_ptrs->general_params;
557 u16 gen_flags = iwl_mld_scan_get_cmd_gen_flags(mld, params, vif,564 u16 gen_flags = iwl_mld_scan_get_cmd_gen_flags(mld, params, vif,
558 scan_status);565 scan_status);
559 u8 gen_flags2 = iwl_mld_scan_get_cmd_gen_flags2(mld, params, vif,566 u8 gen_flags2 = iwl_mld_scan_get_cmd_gen_flags2(mld, params, vif,
@@ -566,7 +573,7 @@ iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld, · 6 unmodified lines
566 gp->flags = cpu_to_le16(gen_flags);573 gp->flags = cpu_to_le16(gen_flags);
567 gp->flags2 = gen_flags2;574 gp->flags2 = gen_flags2;
568 575
569 iwl_mld_scan_cmd_set_dwell(mld, gp, params);576 iwl_mld_scan_cmd_set_dwell(mld, params, scan_ptrs);
570 577
571 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1)578 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1)
572 gp->num_of_fragments[SCAN_LB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;579 gp->num_of_fragments[SCAN_LB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;
@@ -577,9 +584,12 @@ iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld, · 4 unmodified lines
577 584
578static int585static int
579iwl_mld_scan_cmd_set_sched_params(struct iwl_mld_scan_params *params,586iwl_mld_scan_cmd_set_sched_params(struct iwl_mld_scan_params *params,
580 struct iwl_scan_umac_schedule *schedule,587 struct iwl_scan_req_params_ptrs *scan_ptrs)
581 __le16 *delay)
582{588{
589 struct iwl_scan_umac_schedule *schedule =
590 scan_ptrs->periodic_params->schedule;
591 __le16 *delay = &scan_ptrs->periodic_params->delay;
592
583 if (WARN_ON(!params->n_scan_plans ||593 if (WARN_ON(!params->n_scan_plans ||
584 params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))594 params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
585 return -EINVAL;595 return -EINVAL;
@@ -657,11 +667,12 @@ iwl_mld_scan_cmd_build_ssids(struct iwl_mld_scan_params *params, · 71 unmodified lines
657 667
658static void668static void
659iwl_mld_scan_fill_6g_chan_list(struct iwl_mld_scan_params *params,669iwl_mld_scan_fill_6g_chan_list(struct iwl_mld_scan_params *params,
660 struct iwl_scan_probe_params_v4 *pp)670 struct iwl_scan_req_params_ptrs *scan_ptrs)
661{671{
662 int j, idex_s = 0, idex_b = 0;672 int j, idex_s = 0, idex_b = 0;
663 struct cfg80211_scan_6ghz_params *scan_6ghz_params =673 struct cfg80211_scan_6ghz_params *scan_6ghz_params =
664 params->scan_6ghz_params;674 params->scan_6ghz_params;
675 struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params;
665 676
666 for (j = 0;677 for (j = 0;
667 j < params->n_ssids && idex_s < SCAN_SHORT_SSID_MAX_SIZE;678 j < params->n_ssids && idex_s < SCAN_SHORT_SSID_MAX_SIZE;
@@ -725,13 +736,15 @@ iwl_mld_scan_fill_6g_chan_list(struct iwl_mld_scan_params *params, · 57 unmodified lines
725 736
726static void737static void
727iwl_mld_scan_cmd_set_probe_params(struct iwl_mld_scan_params *params,738iwl_mld_scan_cmd_set_probe_params(struct iwl_mld_scan_params *params,
728 struct iwl_scan_probe_params_v4 *pp,739 struct iwl_scan_req_params_ptrs *scan_ptrs,
729 u32 *bitmap_ssid)740 u32 *bitmap_ssid)
730{741{
742 struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params;
743
731 pp->preq = params->preq;744 pp->preq = params->preq;
732 745
733 if (params->scan_6ghz) {746 if (params->scan_6ghz) {
734 iwl_mld_scan_fill_6g_chan_list(params, pp);747 iwl_mld_scan_fill_6g_chan_list(params, scan_ptrs);
735 return;748 return;
736 }749 }
737 750
@@ -821,10 +834,12 @@ static u32 iwl_mld_scan_ch_n_aps_flag(enum nl80211_iftype vif_type, u8 ch_id) · 83 unmodified lines
821static void834static void
822iwl_mld_scan_cmd_set_channels(struct iwl_mld *mld,835iwl_mld_scan_cmd_set_channels(struct iwl_mld *mld,
823 struct ieee80211_channel **channels,836 struct ieee80211_channel **channels,
824 struct iwl_scan_channel_params_v7 *cp,837 struct iwl_scan_req_params_ptrs *scan_ptrs,
825 int n_channels, u32 flags,838 int n_channels, u32 flags,
826 enum nl80211_iftype vif_type)839 enum nl80211_iftype vif_type)
827{840{
841 struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params;
842
828 for (int i = 0; i < n_channels; i++) {843 for (int i = 0; i < n_channels; i++) {
829 enum nl80211_band band = channels[i]->band;844 enum nl80211_band band = channels[i]->band;
830 struct iwl_scan_channel_cfg_umac *cfg = &cp->channel_config[i];845 struct iwl_scan_channel_cfg_umac *cfg = &cp->channel_config[i];
@@ -862,10 +877,11 @@ static u8 · 31 unmodified lines
862iwl_mld_scan_cfg_channels_6g(struct iwl_mld *mld,877iwl_mld_scan_cfg_channels_6g(struct iwl_mld *mld,
863 struct iwl_mld_scan_params *params,878 struct iwl_mld_scan_params *params,
864 u32 n_channels,879 u32 n_channels,
865 struct iwl_scan_probe_params_v4 *pp,880 struct iwl_scan_req_params_ptrs *scan_ptrs,
866 struct iwl_scan_channel_params_v7 *cp,
867 enum nl80211_iftype vif_type)881 enum nl80211_iftype vif_type)
868{882{
883 struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params;
884 struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params;
869 struct cfg80211_scan_6ghz_params *scan_6ghz_params =885 struct cfg80211_scan_6ghz_params *scan_6ghz_params =
870 params->scan_6ghz_params;886 params->scan_6ghz_params;
871 u32 i;887 u32 i;
@@ -1063,25 +1079,23 @@ static int · 191 unmodified lines
1063iwl_mld_scan_cmd_set_6ghz_chan_params(struct iwl_mld *mld,1079iwl_mld_scan_cmd_set_6ghz_chan_params(struct iwl_mld *mld,
1064 struct iwl_mld_scan_params *params,1080 struct iwl_mld_scan_params *params,
1065 struct ieee80211_vif *vif,1081 struct ieee80211_vif *vif,
1066 struct iwl_scan_req_params_v17 *scan_p)1082 struct iwl_scan_req_params_ptrs *scan_ptrs)
1067{1083{
1068 struct iwl_scan_channel_params_v7 *chan_p = &scan_p->channel_params;1084 struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params;
1069 struct iwl_scan_probe_params_v4 *probe_p = &scan_p->probe_params;
1070 1085
1071 /* Explicitly clear the flags since most of them are not1086 /* Explicitly clear the flags since most of them are not
1072 * relevant for 6 GHz scan.1087 * relevant for 6 GHz scan.
1073 */1088 */
1074 chan_p->flags = 0;1089 cp->flags = 0;
1075 chan_p->count = iwl_mld_scan_cfg_channels_6g(mld, params,1090 cp->count = iwl_mld_scan_cfg_channels_6g(mld, params,
1076 params->n_channels,1091 params->n_channels,
1077 probe_p, chan_p,1092 scan_ptrs, vif->type);
1078 vif->type);1093 if (!cp->count)
1079 if (!chan_p->count)
1080 return -EINVAL;1094 return -EINVAL;
1081 1095
1082 if (!params->n_ssids ||1096 if (!params->n_ssids ||
1083 (params->n_ssids == 1 && !params->ssids[0].ssid_len))1097 (params->n_ssids == 1 && !params->ssids[0].ssid_len))
1084 chan_p->flags |= IWL_SCAN_CHANNEL_FLAG_6G_PSC_NO_FILTER;1098 cp->flags |= IWL_SCAN_CHANNEL_FLAG_6G_PSC_NO_FILTER;
1085 1099
1086 return 0;1100 return 0;
1087}1101}
@@ -1090,12 +1104,12 @@ static int · 2 unmodified lines
1090iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld,1104iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld,
1091 struct iwl_mld_scan_params *params,1105 struct iwl_mld_scan_params *params,
1092 struct ieee80211_vif *vif,1106 struct ieee80211_vif *vif,
1093 struct iwl_scan_req_params_v17 *scan_p,1107 struct iwl_scan_req_params_ptrs *scan_ptrs,
1094 bool low_latency,1108 bool low_latency,
1095 enum iwl_mld_scan_status scan_status,1109 enum iwl_mld_scan_status scan_status,
1096 u32 channel_cfg_flags)1110 u32 channel_cfg_flags)
1097{1111{
1098 struct iwl_scan_channel_params_v7 *cp = &scan_p->channel_params;1112 struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params;
1099 struct ieee80211_supported_band *sband =1113 struct ieee80211_supported_band *sband =
1100 &mld->nvm_data->bands[NL80211_BAND_6GHZ];1114 &mld->nvm_data->bands[NL80211_BAND_6GHZ];
1101 1115
@@ -1107,14 +1121,14 @@ iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld, · 5 unmodified lines
1107 1121
1108 if (params->scan_6ghz)1122 if (params->scan_6ghz)
1109 return iwl_mld_scan_cmd_set_6ghz_chan_params(mld, params,1123 return iwl_mld_scan_cmd_set_6ghz_chan_params(mld, params,
1110 vif, scan_p);1124 vif, scan_ptrs);
1111 1125
1112 /* relevant only for 2.4 GHz/5 GHz scan */1126 /* relevant only for 2.4 GHz/5 GHz scan */
1113 cp->flags = iwl_mld_scan_cmd_set_chan_flags(mld, params, vif,1127 cp->flags = iwl_mld_scan_cmd_set_chan_flags(mld, params, vif,
1114 low_latency);1128 low_latency);
1115 cp->count = params->n_channels;1129 cp->count = params->n_channels;
1116 1130
1117 iwl_mld_scan_cmd_set_channels(mld, params->channels, cp,1131 iwl_mld_scan_cmd_set_channels(mld, params->channels, scan_ptrs,
1118 params->n_channels, channel_cfg_flags,1132 params->n_channels, channel_cfg_flags,
1119 vif->type);1133 vif->type);
1120 1134
@@ -1144,49 +1158,148 @@ iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld, · 23 unmodified lines
1144 return 0;1158 return 0;
1145}1159}
1146 1160
1147static int1161struct iwl_scan_umac_handler {
1148iwl_mld_scan_build_cmd(struct iwl_mld *mld, struct ieee80211_vif *vif,1162 u8 version;
1163 int (*handler)(struct iwl_mld *mld, struct ieee80211_vif *vif,
1149 struct iwl_mld_scan_params *params,1164 struct iwl_mld_scan_params *params,
1150 enum iwl_mld_scan_status scan_status,1165 enum iwl_mld_scan_status scan_status,
1151 bool low_latency)1166 int uid, u32 ooc_priority, bool low_latency);
1167};
1168
1169#define IWL_SCAN_UMAC_HANDLER(_ver) { \
1170 .version = _ver, \
1171 .handler = iwl_mld_scan_umac_v##_ver, \
1172}
1173
1174static int iwl_mld_scan_umac_common(struct iwl_mld *mld,
1175 struct ieee80211_vif *vif,
1176 struct iwl_mld_scan_params *params,
1177 struct iwl_scan_req_params_ptrs *scan_ptrs,
1178 enum iwl_mld_scan_status scan_status,
1179 bool low_latency)
1152{1180{
1153 struct iwl_scan_req_umac_v17 *cmd = mld->scan.cmd;
1154 struct iwl_scan_req_params_v17 *scan_p = &cmd->scan_params;
1155 u32 bitmap_ssid = 0;1181 u32 bitmap_ssid = 0;
1156 int uid, ret;1182 int ret;
1157 1183
1158 memset(mld->scan.cmd, 0, mld->scan.cmd_size);1184 iwl_mld_scan_cmd_set_gen_params(mld, params, vif, scan_ptrs,
1185 scan_status);
1159 1186
1160 /* find a free UID entry */1187 ret = iwl_mld_scan_cmd_set_sched_params(params, scan_ptrs);
1161 uid = iwl_mld_scan_uid_by_status(mld, IWL_MLD_SCAN_NONE);1188 if (ret)
1162 if (uid < 0)1189 return ret;
1163 return uid;
1164 1190
1165 cmd->uid = cpu_to_le32(uid);1191 iwl_mld_scan_cmd_set_probe_params(params, scan_ptrs, &bitmap_ssid);
1166 cmd->ooc_priority =1192
1167 cpu_to_le32(iwl_mld_scan_ooc_priority(scan_status));1193 return iwl_mld_scan_cmd_set_chan_params(mld, params, vif, scan_ptrs,
1194 low_latency, scan_status,
1195 bitmap_ssid);
1196}
1197
1198static int iwl_mld_scan_umac_v18(struct iwl_mld *mld, struct ieee80211_vif *vif,
1199 struct iwl_mld_scan_params *params,
1200 enum iwl_mld_scan_status scan_status,
1201 int uid, u32 ooc_priority, bool low_latency)
1202{
1203 struct iwl_scan_req_umac_v18 *cmd = mld->scan.cmd;
1204 struct iwl_scan_req_params_ptrs scan_ptrs = {
1205 .general_params = &cmd->scan_params.general_params,
1206 .probe_params = &cmd->scan_params.probe_params,
1207 .channel_params = &cmd->scan_params.channel_params,
1208 .periodic_params = &cmd->scan_params.periodic_params
1209 };
1210 int ret;
1168 1211
1169 iwl_mld_scan_cmd_set_gen_params(mld, params, vif,1212 if (WARN_ON(params->n_channels > SCAN_MAX_NUM_CHANS_V4))
1170 &scan_p->general_params, scan_status);1213 return -EINVAL;
1171 1214
1172 ret = iwl_mld_scan_cmd_set_sched_params(params,1215 cmd->uid = cpu_to_le32(uid);
1173 scan_p->periodic_params.schedule,1216 cmd->ooc_priority = cpu_to_le32(ooc_priority);
1174 &scan_p->periodic_params.delay);1217
1218 ret = iwl_mld_scan_umac_common(mld, vif, params, &scan_ptrs,
1219 scan_status, low_latency);
1175 if (ret)1220 if (ret)
1176 return ret;1221 return ret;
1177 1222
1178 iwl_mld_scan_cmd_set_probe_params(params, &scan_p->probe_params,1223 return uid;
1179 &bitmap_ssid);1224}
1225
1226static int iwl_mld_scan_umac_v17(struct iwl_mld *mld, struct ieee80211_vif *vif,
1227 struct iwl_mld_scan_params *params,
1228 enum iwl_mld_scan_status scan_status,
1229 int uid, u32 ooc_priority, bool low_latency)
1230{
1231 struct iwl_scan_req_umac_v17 *cmd = mld->scan.cmd;
1232 struct iwl_scan_req_params_ptrs scan_ptrs = {
1233 .general_params = &cmd->scan_params.general_params,
1234 .probe_params = &cmd->scan_params.probe_params,
1235
1236 /* struct iwl_scan_channel_params_v8 and struct
1237 * iwl_scan_channel_params_v7 are almost identical. The only
1238 * difference is that the newer version allows configuration of
1239 * more channels. So casting here is ok as long as we ensure
1240 * that we don't exceed the max number of channels supported by
1241 * the older version (see the WARN_ON below).
1242 */
1243 .channel_params = (struct iwl_scan_channel_params_v8 *)
1244 &cmd->scan_params.channel_params,
1245 .periodic_params = &cmd->scan_params.periodic_params
1246 };
1247 int ret;
1248
1249 if (WARN_ON(params->n_channels > SCAN_MAX_NUM_CHANS_V3))
1250 return -EINVAL;
1251
1252 cmd->uid = cpu_to_le32(uid);
1253 cmd->ooc_priority = cpu_to_le32(ooc_priority);
1180 1254
1181 ret = iwl_mld_scan_cmd_set_chan_params(mld, params, vif, scan_p,1255 ret = iwl_mld_scan_umac_common(mld, vif, params, &scan_ptrs,
1182 low_latency, scan_status,1256 scan_status, low_latency);
1183 bitmap_ssid);
1184 if (ret)1257 if (ret)
1185 return ret;1258 return ret;
1186 1259
1187 return uid;1260 return uid;
1188}1261}
1189 1262
1263static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = {
1264 /* set the newest version first to shorten the list traverse time */
1265 IWL_SCAN_UMAC_HANDLER(18),
1266 IWL_SCAN_UMAC_HANDLER(17),
1267};
1268
1269static int
1270iwl_mld_scan_build_cmd(struct iwl_mld *mld, struct ieee80211_vif *vif,
1271 struct iwl_mld_scan_params *params,
1272 enum iwl_mld_scan_status scan_status,
1273 bool low_latency)
1274{
1275 int uid, err;
1276 u32 ooc_priority;
1277
1278 memset(mld->scan.cmd, 0, mld->scan.cmd_size);
1279 uid = iwl_mld_scan_uid_by_status(mld, IWL_MLD_SCAN_NONE);
1280 if (uid < 0)
1281 return uid;
1282
1283 ooc_priority = iwl_mld_scan_ooc_priority(scan_status);
1284
1285 for (size_t i = 0; i < ARRAY_SIZE(iwl_scan_umac_handlers); i++) {
1286 const struct iwl_scan_umac_handler *ver_handler =
1287 &iwl_scan_umac_handlers[i];
1288
1289 if (ver_handler->version != mld->scan.cmd_ver)
1290 continue;
1291
1292 err = ver_handler->handler(mld, vif, params, scan_status,
1293 uid, ooc_priority, low_latency);
1294 return err ? : uid;
1295 }
1296
1297 IWL_ERR(mld, "No handler for UMAC scan cmd version %d\n",
1298 mld->scan.cmd_ver);
1299
1300 return -EINVAL;
1301}
1302
1190static bool1303static bool
1191iwl_mld_scan_pass_all(struct iwl_mld *mld,1304iwl_mld_scan_pass_all(struct iwl_mld *mld,
1192 struct cfg80211_sched_scan_request *req)1305 struct cfg80211_sched_scan_request *req)
@@ -1942,9 +2055,7 @@ void iwl_mld_handle_scan_complete_notif(struct iwl_mld *mld, · 749 unmodified lines
1942 struct ieee80211_bss_conf *link_conf = NULL;2055 struct ieee80211_bss_conf *link_conf = NULL;
1943 2056
1944 if (fw_link_id != IWL_MLD_INVALID_FW_ID)2057 if (fw_link_id != IWL_MLD_INVALID_FW_ID)
1945 link_conf =2058 link_conf = iwl_mld_fw_id_to_link_conf(mld, fw_link_id);
1946 wiphy_dereference(mld->wiphy,
1947 mld->fw_id_to_bss_conf[fw_link_id]);
1948 2059
1949 /* It is possible that by the time the scan is complete the2060 /* It is possible that by the time the scan is complete the
1950 * link was already removed and is not valid.2061 * link was already removed and is not valid.
@@ -2031,6 +2142,8 @@ int iwl_mld_alloc_scan_cmd(struct iwl_mld *mld) · 80 unmodified lines
2031 2142
2032 if (scan_cmd_ver == 17) {2143 if (scan_cmd_ver == 17) {
2033 scan_cmd_size = sizeof(struct iwl_scan_req_umac_v17);2144 scan_cmd_size = sizeof(struct iwl_scan_req_umac_v17);
2145 } else if (scan_cmd_ver == 18) {
2146 scan_cmd_size = sizeof(struct iwl_scan_req_umac_v18);
2034 } else {2147 } else {
2035 IWL_ERR(mld, "Unexpected scan cmd version %d\n", scan_cmd_ver);2148 IWL_ERR(mld, "Unexpected scan cmd version %d\n", scan_cmd_ver);
2036 return -EINVAL;2149 return -EINVAL;
@@ -2041,6 +2154,7 @@ int iwl_mld_alloc_scan_cmd(struct iwl_mld *mld) · 4 unmodified lines
2041 return -ENOMEM;2154 return -ENOMEM;
2042 2155
2043 mld->scan.cmd_size = scan_cmd_size;2156 mld->scan.cmd_size = scan_cmd_size;
2157 mld->scan.cmd_ver = scan_cmd_ver;
2044 2158
2045 return 0;2159 return 0;
2046}2160}
drivers/net/wireless/intel/iwlwifi/mld/scan.h+2−0
@@ -109,6 +109,7 @@ enum iwl_mld_traffic_load { · 108 unmodified lines
109 * @traffic_load.status: The current traffic load status, see109 * @traffic_load.status: The current traffic load status, see
110 * &enum iwl_mld_traffic_load110 * &enum iwl_mld_traffic_load
111 * @cmd_size: size of %cmd.111 * @cmd_size: size of %cmd.
112 * @cmd_ver: version of the scan command format.
112 * @cmd: pointer to scan cmd buffer (allocated once in op mode start).113 * @cmd: pointer to scan cmd buffer (allocated once in op mode start).
113 * @last_6ghz_passive_jiffies: stores the last 6GHz passive scan time114 * @last_6ghz_passive_jiffies: stores the last 6GHz passive scan time
114 * in jiffies.115 * in jiffies.
@@ -134,6 +135,7 @@ struct iwl_mld_scan { · 19 unmodified lines
134 /* And here fields that survive a fw restart */135 /* And here fields that survive a fw restart */
135 size_t cmd_size;136 size_t cmd_size;
136 void *cmd;137 void *cmd;
138 u8 cmd_ver;
137 unsigned long last_6ghz_passive_jiffies;139 unsigned long last_6ghz_passive_jiffies;
138 unsigned long last_start_time_jiffies;140 unsigned long last_start_time_jiffies;
139 u64 last_mlo_scan_time;141 u64 last_mlo_scan_time;
drivers/net/wireless/intel/iwlwifi/mld/sta.c+40−10
@@ -398,12 +398,42 @@ static u32 iwl_mld_get_htc_flags(struct ieee80211_link_sta *link_sta) · 397 unmodified lines
398 return htc_flags;398 return htc_flags;
399}399}
400 400
401/* Note: modifies the command depending on FW command version */
401static int iwl_mld_send_sta_cmd(struct iwl_mld *mld,402static int iwl_mld_send_sta_cmd(struct iwl_mld *mld,
402 const struct iwl_sta_cfg_cmd *cmd)403 struct iwl_sta_cfg_cmd *cmd)
403{404{
404 int ret = iwl_mld_send_cmd_pdu(mld,405 int cmd_id = WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD);
405 WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD),406 int cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0);
406 cmd);407 int len = sizeof(*cmd);
408 int ret;
409
410 if (cmd_ver < 2) {
411 IWL_ERR(mld, "Unsupported STA_CONFIG_CMD version %d\n",
412 cmd_ver);
413 return -EINVAL;
414 } else if (cmd_ver == 2) {
415 struct iwl_sta_cfg_cmd_v2 *cmd_v2 = (void *)cmd;
416
417 if (WARN_ON(cmd->station_type == cpu_to_le32(STATION_TYPE_NAN_PEER_NMI) ||
418 cmd->station_type == cpu_to_le32(STATION_TYPE_NAN_PEER_NDI) ||
419 hweight32(le32_to_cpu(cmd->link_mask)) != 1))
420 return -EINVAL;
421 /*
422 * These fields are located in a different place in the struct of v2.
423 * The assumption is that UHR won't be used with FW that has v2.
424 */
425 if (WARN_ON(cmd->mic_prep_pad_delay || cmd->mic_compute_pad_delay))
426 return -EINVAL;
427
428 len = sizeof(struct iwl_sta_cfg_cmd_v2);
429 cmd_v2->link_id = cpu_to_le32(__ffs(le32_to_cpu(cmd->link_mask)));
430 } else if (WARN_ON(cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_PEER_NMI) &&
431 cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_PEER_NDI) &&
432 hweight32(le32_to_cpu(cmd->link_mask)) != 1)) {
433 return -EINVAL;
434 }
435
436 ret = iwl_mld_send_cmd_pdu(mld, cmd_id, cmd, len);
407 if (ret)437 if (ret)
408 IWL_ERR(mld, "STA_CONFIG_CMD send failed, ret=0x%x\n", ret);438 IWL_ERR(mld, "STA_CONFIG_CMD send failed, ret=0x%x\n", ret);
409 return ret;439 return ret;
@@ -431,8 +461,8 @@ iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, · 21 unmodified lines
431 return -EINVAL;461 return -EINVAL;
432 462
433 cmd.sta_id = cpu_to_le32(fw_id);463 cmd.sta_id = cpu_to_le32(fw_id);
464 cmd.link_mask = cpu_to_le32(BIT(mld_link->fw_id));
434 cmd.station_type = cpu_to_le32(mld_sta->sta_type);465 cmd.station_type = cpu_to_le32(mld_sta->sta_type);
435 cmd.link_id = cpu_to_le32(mld_link->fw_id);
436 466
437 memcpy(&cmd.peer_mld_address, sta->addr, ETH_ALEN);467 memcpy(&cmd.peer_mld_address, sta->addr, ETH_ALEN);
438 memcpy(&cmd.peer_link_address, link_sta->addr, ETH_ALEN);468 memcpy(&cmd.peer_link_address, link_sta->addr, ETH_ALEN);
@@ -498,7 +528,7 @@ iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, · 59 unmodified lines
498 return iwl_mld_send_sta_cmd(mld, &cmd);528 return iwl_mld_send_sta_cmd(mld, &cmd);
499}529}
500 530
501IWL_MLD_ALLOC_FN(link_sta, link_sta)531static IWL_MLD_ALLOC_FN(link_sta, link_sta)
502 532
503static int533static int
504iwl_mld_add_link_sta(struct iwl_mld *mld, struct ieee80211_link_sta *link_sta)534iwl_mld_add_link_sta(struct iwl_mld *mld, struct ieee80211_link_sta *link_sta)
@@ -725,14 +755,14 @@ iwl_mld_init_sta(struct iwl_mld *mld, struct ieee80211_sta *sta, · 220 unmodified lines
725}755}
726 756
727int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,757int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
728 struct ieee80211_vif *vif, enum iwl_fw_sta_type type)758 struct ieee80211_vif *vif)
729{759{
730 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);760 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
731 struct ieee80211_link_sta *link_sta;761 struct ieee80211_link_sta *link_sta;
732 int link_id;762 int link_id;
733 int ret;763 int ret;
734 764
735 ret = iwl_mld_init_sta(mld, sta, vif, type);765 ret = iwl_mld_init_sta(mld, sta, vif, STATION_TYPE_PEER);
736 if (ret)766 if (ret)
737 return ret;767 return ret;
738 768
@@ -908,7 +938,7 @@ static void iwl_mld_count_mpdu(struct ieee80211_link_sta *link_sta, int queue, · 169 unmodified lines
908 if (!(mld_vif->emlsr.blocked_reasons & IWL_MLD_EMLSR_BLOCKED_TPT))938 if (!(mld_vif->emlsr.blocked_reasons & IWL_MLD_EMLSR_BLOCKED_TPT))
909 goto unlock;939 goto unlock;
910 940
911 for (int i = 0; i <= IWL_FW_MAX_LINK_ID; i++)941 for (int i = 0; i < IWL_FW_MAX_LINKS; i++)
912 total_mpdus += tx ? queue_counter->per_link[i].tx :942 total_mpdus += tx ? queue_counter->per_link[i].tx :
913 queue_counter->per_link[i].rx;943 queue_counter->per_link[i].rx;
914 944
@@ -982,7 +1012,7 @@ iwl_mld_add_internal_sta_to_fw(struct iwl_mld *mld, · 67 unmodified lines
982 return iwl_mld_send_aux_sta_cmd(mld, internal_sta);1012 return iwl_mld_send_aux_sta_cmd(mld, internal_sta);
983 1013
984 cmd.sta_id = cpu_to_le32((u8)internal_sta->sta_id);1014 cmd.sta_id = cpu_to_le32((u8)internal_sta->sta_id);
985 cmd.link_id = cpu_to_le32(fw_link_id);1015 cmd.link_mask = cpu_to_le32(BIT(fw_link_id));
986 cmd.station_type = cpu_to_le32(internal_sta->sta_type);1016 cmd.station_type = cpu_to_le32(internal_sta->sta_type);
987 1017
988 /* FW doesn't allow to add a IGTK/BIGTK if the sta isn't marked as MFP.1018 /* FW doesn't allow to add a IGTK/BIGTK if the sta isn't marked as MFP.
drivers/net/wireless/intel/iwlwifi/mld/sta.h+2−2
@@ -89,7 +89,7 @@ struct iwl_mld_per_link_mpdu_counter { · 88 unmodified lines
89 */89 */
90struct iwl_mld_per_q_mpdu_counter {90struct iwl_mld_per_q_mpdu_counter {
91 spinlock_t lock;91 spinlock_t lock;
92 struct iwl_mld_per_link_mpdu_counter per_link[IWL_FW_MAX_LINK_ID + 1];92 struct iwl_mld_per_link_mpdu_counter per_link[IWL_FW_MAX_LINKS];
93 unsigned long window_start_time;93 unsigned long window_start_time;
94} ____cacheline_aligned_in_smp;94} ____cacheline_aligned_in_smp;
95 95
@@ -190,7 +190,7 @@ iwl_mld_link_sta_from_mac80211(struct ieee80211_link_sta *link_sta) · 94 unmodified lines
190}190}
191 191
192int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,192int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
193 struct ieee80211_vif *vif, enum iwl_fw_sta_type type);193 struct ieee80211_vif *vif);
194void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta);194void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta);
195int iwl_mld_fw_sta_id_from_link_sta(struct iwl_mld *mld,195int iwl_mld_fw_sta_id_from_link_sta(struct iwl_mld *mld,
196 struct ieee80211_link_sta *link_sta);196 struct ieee80211_link_sta *link_sta);
drivers/net/wireless/intel/iwlwifi/mld/stats.c+27−4
@@ -369,15 +369,39 @@ out: · 368 unmodified lines
369static void iwl_mld_update_link_sig(struct ieee80211_vif *vif, int sig,369static void iwl_mld_update_link_sig(struct ieee80211_vif *vif, int sig,
370 struct ieee80211_bss_conf *bss_conf)370 struct ieee80211_bss_conf *bss_conf)
371{371{
372 struct iwl_mld_link *link = iwl_mld_link_from_mac80211(bss_conf);
372 struct iwl_mld *mld = iwl_mld_vif_from_mac80211(vif)->mld;373 struct iwl_mld *mld = iwl_mld_vif_from_mac80211(vif)->mld;
373 int exit_emlsr_thresh;374 int exit_emlsr_thresh;
375 int last_event;
374 376
375 if (sig == 0) {377 if (sig == 0) {
376 IWL_DEBUG_RX(mld, "RSSI is 0 - skip signal based decision\n");378 IWL_DEBUG_RX(mld, "RSSI is 0 - skip signal based decision\n");
377 return;379 return;
378 }380 }
379 381
380 /* TODO: task=statistics handle CQM notifications */382 if (WARN_ON(!link))
383 return;
384
385 /* CQM Notification */
386 if (vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI) {
387 int thold = bss_conf->cqm_rssi_thold;
388 int hyst = bss_conf->cqm_rssi_hyst;
389
390 last_event = link->last_cqm_rssi_event;
391 if (thold && sig < thold &&
392 (last_event == 0 || sig < last_event - hyst)) {
393 link->last_cqm_rssi_event = sig;
394 ieee80211_cqm_rssi_notify(vif,
395 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
396 sig, GFP_KERNEL);
397 } else if (sig > thold &&
398 (last_event == 0 || sig > last_event + hyst)) {
399 link->last_cqm_rssi_event = sig;
400 ieee80211_cqm_rssi_notify(vif,
401 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
402 sig, GFP_KERNEL);
403 }
404 }
381 405
382 if (!iwl_mld_emlsr_active(vif)) {406 if (!iwl_mld_emlsr_active(vif)) {
383 /* We're not in EMLSR and our signal is bad,407 /* We're not in EMLSR and our signal is bad,
@@ -407,14 +431,13 @@ iwl_mld_process_per_link_stats(struct iwl_mld *mld, · 23 unmodified lines
407 u32 total_airtime_usec = 0;431 u32 total_airtime_usec = 0;
408 432
409 for (u32 fw_id = 0;433 for (u32 fw_id = 0;
410 fw_id < ARRAY_SIZE(mld->fw_id_to_bss_conf);434 fw_id < mld->fw->ucode_capa.num_links;
411 fw_id++) {435 fw_id++) {
412 const struct iwl_stats_ntfy_per_link *link_stats;436 const struct iwl_stats_ntfy_per_link *link_stats;
413 struct ieee80211_bss_conf *bss_conf;437 struct ieee80211_bss_conf *bss_conf;
414 int sig;438 int sig;
415 439
416 bss_conf = wiphy_dereference(mld->wiphy,440 bss_conf = iwl_mld_fw_id_to_link_conf(mld, fw_id);
417 mld->fw_id_to_bss_conf[fw_id]);
418 if (!bss_conf || bss_conf->vif->type != NL80211_IFTYPE_STATION)441 if (!bss_conf || bss_conf->vif->type != NL80211_IFTYPE_STATION)
419 continue;442 continue;
420 443
drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c+4−4
@@ -42,7 +42,7 @@ int iwlmld_kunit_test_init(struct kunit *test) · 41 unmodified lines
42 iwl_construct_mld(mld, trans, cfg, fw, hw, NULL);42 iwl_construct_mld(mld, trans, cfg, fw, hw, NULL);
43 43
44 fw->ucode_capa.num_stations = IWL_STATION_COUNT_MAX;44 fw->ucode_capa.num_stations = IWL_STATION_COUNT_MAX;
45 fw->ucode_capa.num_links = IWL_FW_MAX_LINK_ID + 1;45 fw->ucode_capa.num_links = IWL_FW_MAX_LINKS;
46 46
47 mld->fwrt.trans = trans;47 mld->fwrt.trans = trans;
48 mld->fwrt.fw = fw;48 mld->fwrt.fw = fw;
@@ -68,7 +68,7 @@ int iwlmld_kunit_test_init(struct kunit *test) · 19 unmodified lines
68 return 0;68 return 0;
69}69}
70 70
71IWL_MLD_ALLOC_FN(link, bss_conf)71static IWL_MLD_ALLOC_FN(link, bss_conf)
72 72
73static void iwlmld_kunit_init_link(struct ieee80211_vif *vif,73static void iwlmld_kunit_init_link(struct ieee80211_vif *vif,
74 struct ieee80211_bss_conf *link,74 struct ieee80211_bss_conf *link,
@@ -94,7 +94,7 @@ static void iwlmld_kunit_init_link(struct ieee80211_vif *vif, · 19 unmodified lines
94 rcu_assign_pointer(vif->link_conf[link_id], link);94 rcu_assign_pointer(vif->link_conf[link_id], link);
95}95}
96 96
97IWL_MLD_ALLOC_FN(vif, vif)97static IWL_MLD_ALLOC_FN(vif, vif)
98 98
99/* Helper function to add and initialize a VIF for KUnit tests */99/* Helper function to add and initialize a VIF for KUnit tests */
100struct ieee80211_vif *iwlmld_kunit_add_vif(bool mlo, enum nl80211_iftype type)100struct ieee80211_vif *iwlmld_kunit_add_vif(bool mlo, enum nl80211_iftype type)
@@ -199,7 +199,7 @@ void iwlmld_kunit_assign_chanctx_to_link(struct ieee80211_vif *vif, · 98 unmodified lines
199 vif->active_links |= BIT(link->link_id);199 vif->active_links |= BIT(link->link_id);
200}200}
201 201
202IWL_MLD_ALLOC_FN(link_sta, link_sta)202static IWL_MLD_ALLOC_FN(link_sta, link_sta)
203 203
204static void iwlmld_kunit_add_link_sta(struct ieee80211_sta *sta,204static void iwlmld_kunit_add_link_sta(struct ieee80211_sta *sta,
205 struct ieee80211_link_sta *link_sta,205 struct ieee80211_link_sta *link_sta,
drivers/net/wireless/intel/iwlwifi/mld/tlc.c+73−5
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include "hcmd.h"9#include "hcmd.h"
10#include "sta.h"10#include "sta.h"
11#include "phy.h"11#include "phy.h"
12#include "iface.h"
12 13
13#include "fw/api/rs.h"14#include "fw/api/rs.h"
14#include "fw/api/context.h"15#include "fw/api/context.h"
@@ -36,7 +37,8 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld, · 21 unmodified lines
36 struct ieee80211_vif *vif,37 struct ieee80211_vif *vif,
37 struct ieee80211_link_sta *link_sta,38 struct ieee80211_link_sta *link_sta,
38 const struct ieee80211_sta_he_cap *own_he_cap,39 const struct ieee80211_sta_he_cap *own_he_cap,
39 const struct ieee80211_sta_eht_cap *own_eht_cap)40 const struct ieee80211_sta_eht_cap *own_eht_cap,
41 const struct ieee80211_sta_uhr_cap *own_uhr_cap)
40{42{
41 struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;43 struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
42 struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;44 struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
@@ -90,6 +92,12 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld, · 47 unmodified lines
90 flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK;92 flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK;
91 }93 }
92 94
95 if (link_sta->uhr_cap.has_uhr && own_uhr_cap &&
96 link_sta->uhr_cap.phy.cap & IEEE80211_UHR_PHY_CAP_ELR_RX &&
97 own_uhr_cap->phy.cap & IEEE80211_UHR_PHY_CAP_ELR_TX)
98 flags |= IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK |
99 IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK;
100
93 return cpu_to_le16(flags);101 return cpu_to_le16(flags);
94}102}
95 103
@@ -406,6 +414,7 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif, · 310 unmodified lines
406 struct ieee80211_supported_band *sband,414 struct ieee80211_supported_band *sband,
407 const struct ieee80211_sta_he_cap *own_he_cap,415 const struct ieee80211_sta_he_cap *own_he_cap,
408 const struct ieee80211_sta_eht_cap *own_eht_cap,416 const struct ieee80211_sta_eht_cap *own_eht_cap,
417 const struct ieee80211_sta_uhr_cap *own_uhr_cap,
409 struct iwl_tlc_config_cmd *cmd)418 struct iwl_tlc_config_cmd *cmd)
410{419{
411 int i;420 int i;
@@ -423,7 +432,16 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif, · 11 unmodified lines
423 cmd->non_ht_rates = cpu_to_le16(non_ht_rates);432 cmd->non_ht_rates = cpu_to_le16(non_ht_rates);
424 cmd->mode = IWL_TLC_MNG_MODE_NON_HT;433 cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
425 434
426 if (link_sta->eht_cap.has_eht && own_he_cap && own_eht_cap) {435 if (link_sta->uhr_cap.has_uhr && own_uhr_cap) {
436 cmd->mode = IWL_TLC_MNG_MODE_UHR;
437 /*
438 * FIXME: spec currently inherits from EHT but has no
439 * finer MCS bits. Once that's there, need to add them
440 * to the bitmaps (and maybe copy this to UHR, or so.)
441 */
442 iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap,
443 own_eht_cap, cmd);
444 } else if (link_sta->eht_cap.has_eht && own_he_cap && own_eht_cap) {
427 cmd->mode = IWL_TLC_MNG_MODE_EHT;445 cmd->mode = IWL_TLC_MNG_MODE_EHT;
428 iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap,446 iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap,
429 own_eht_cap, cmd);447 own_eht_cap, cmd);
@@ -513,19 +531,23 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, · 83 unmodified lines
513 struct ieee80211_bss_conf *link)531 struct ieee80211_bss_conf *link)
514{532{
515 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);533 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);
534 struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
516 enum nl80211_band band = link->chanreq.oper.chan->band;535 enum nl80211_band band = link->chanreq.oper.chan->band;
517 struct ieee80211_supported_band *sband = mld->hw->wiphy->bands[band];536 struct ieee80211_supported_band *sband = mld->hw->wiphy->bands[band];
518 const struct ieee80211_sta_he_cap *own_he_cap =537 const struct ieee80211_sta_he_cap *own_he_cap =
519 ieee80211_get_he_iftype_cap_vif(sband, vif);538 ieee80211_get_he_iftype_cap_vif(sband, vif);
520 const struct ieee80211_sta_eht_cap *own_eht_cap =539 const struct ieee80211_sta_eht_cap *own_eht_cap =
521 ieee80211_get_eht_iftype_cap_vif(sband, vif);540 ieee80211_get_eht_iftype_cap_vif(sband, vif);
541 const struct ieee80211_sta_uhr_cap *own_uhr_cap =
542 ieee80211_get_uhr_iftype_cap_vif(sband, vif);
522 struct iwl_tlc_config_cmd cmd = {543 struct iwl_tlc_config_cmd cmd = {
523 /* For AP mode, use 20 MHz until the STA is authorized */544 /* For AP mode, use 20 MHz until the STA is authorized */
524 .max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ?545 .max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ?
525 iwl_mld_fw_bw_from_sta_bw(link_sta) :546 iwl_mld_fw_bw_from_sta_bw(link_sta) :
526 IWL_TLC_MNG_CH_WIDTH_20MHZ,547 IWL_TLC_MNG_CH_WIDTH_20MHZ,
527 .flags = iwl_mld_get_tlc_cmd_flags(mld, vif, link_sta,548 .flags = iwl_mld_get_tlc_cmd_flags(mld, vif, link_sta,
528 own_he_cap, own_eht_cap),549 own_he_cap, own_eht_cap,
550 own_uhr_cap),
529 .chains = iwl_mld_get_fw_chains(mld),551 .chains = iwl_mld_get_fw_chains(mld),
530 .sgi_ch_width_supp = iwl_mld_get_fw_sgi(link_sta),552 .sgi_ch_width_supp = iwl_mld_get_fw_sgi(link_sta),
531 .max_mpdu_len = cpu_to_le16(link_sta->agg.max_amsdu_len),553 .max_mpdu_len = cpu_to_le16(link_sta->agg.max_amsdu_len),
@@ -546,7 +568,10 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, · 14 unmodified lines
546 568
547 cmd.sta_mask = cpu_to_le32(BIT(fw_sta_id));569 cmd.sta_mask = cpu_to_le32(BIT(fw_sta_id));
548 570
549 chan_ctx = rcu_dereference_wiphy(mld->wiphy, link->chanctx_conf);571 if (WARN_ON_ONCE(!mld_link))
572 return;
573
574 chan_ctx = rcu_dereference_wiphy(mld->wiphy, mld_link->chan_ctx);
550 if (WARN_ON(!chan_ctx))575 if (WARN_ON(!chan_ctx))
551 return;576 return;
552 577
@@ -555,7 +580,7 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, · 2 unmodified lines
555 580
556 iwl_mld_fill_supp_rates(mld, vif, link_sta, sband,581 iwl_mld_fill_supp_rates(mld, vif, link_sta, sband,
557 own_he_cap, own_eht_cap,582 own_he_cap, own_eht_cap,
558 &cmd);583 own_uhr_cap, &cmd);
559 584
560 if (cmd_ver == 6) {585 if (cmd_ver == 6) {
561 cmd_ptr = &cmd;586 cmd_ptr = &cmd;
@@ -638,6 +663,49 @@ void iwl_mld_config_tlc_link(struct iwl_mld *mld, · 76 unmodified lines
638 iwl_mld_send_tlc_cmd(mld, vif, link_sta, link_conf);663 iwl_mld_send_tlc_cmd(mld, vif, link_sta, link_conf);
639}664}
640 665
666void iwl_mld_tlc_update_phy(struct iwl_mld *mld, struct ieee80211_vif *vif,
667 struct ieee80211_bss_conf *link_conf)
668{
669 struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link_conf);
670 struct ieee80211_chanctx_conf *chan_ctx;
671 int link_id = link_conf->link_id;
672 struct ieee80211_sta *sta;
673
674 lockdep_assert_wiphy(mld->wiphy);
675
676 if (WARN_ON(!mld_link))
677 return;
678
679 chan_ctx = rcu_dereference_wiphy(mld->wiphy, mld_link->chan_ctx);
680
681 for_each_station(sta, mld->hw) {
682 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
683 struct iwl_mld_link_sta *mld_link_sta;
684 struct ieee80211_link_sta *link_sta;
685
686 if (mld_sta->vif != vif)
687 continue;
688
689 link_sta = link_sta_dereference_protected(sta, link_id);
690 if (!link_sta)
691 continue;
692
693 mld_link_sta = iwl_mld_link_sta_dereference_check(mld_sta,
694 link_id);
695
696 /* In recovery flow, the station may not be (yet) in the
697 * firmware, don't send a TLC command for a station the
698 * firmware does not know.
699 */
700 if (!mld_link_sta || !mld_link_sta->in_fw)
701 continue;
702
703 if (chan_ctx)
704 iwl_mld_config_tlc_link(mld, vif, link_conf, link_sta);
705 /* TODO: else, remove the TLC object in the firmware */
706 }
707}
708
641void iwl_mld_config_tlc(struct iwl_mld *mld, struct ieee80211_vif *vif,709void iwl_mld_config_tlc(struct iwl_mld *mld, struct ieee80211_vif *vif,
642 struct ieee80211_sta *sta)710 struct ieee80211_sta *sta)
643{711{
drivers/net/wireless/intel/iwlwifi/mld/tlc.h+3−0
@@ -20,4 +20,7 @@ void iwl_mld_handle_tlc_notif(struct iwl_mld *mld, · 19 unmodified lines
20 20
21int iwl_mld_send_tlc_dhc(struct iwl_mld *mld, u8 sta_id, u32 type, u32 data);21int iwl_mld_send_tlc_dhc(struct iwl_mld *mld, u8 sta_id, u32 type, u32 data);
22 22
23void iwl_mld_tlc_update_phy(struct iwl_mld *mld, struct ieee80211_vif *vif,
24 struct ieee80211_bss_conf *link_conf);
25
23#endif /* __iwl_mld_tlc_h__ */26#endif /* __iwl_mld_tlc_h__ */
drivers/net/wireless/intel/iwlwifi/mvm/fw.c+143−14
@@ -459,23 +459,18 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm, · 458 unmodified lines
459 459
460static void iwl_mvm_uats_init(struct iwl_mvm *mvm)460static void iwl_mvm_uats_init(struct iwl_mvm *mvm)
461{461{
462 int cmd_id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
463 MCC_ALLOWED_AP_TYPE_CMD);
464 struct iwl_mcc_allowed_ap_type_cmd_v1 cmd = {};
462 u8 cmd_ver;465 u8 cmd_ver;
463 int ret;466 int ret;
464 struct iwl_host_cmd cmd = {
465 .id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
466 MCC_ALLOWED_AP_TYPE_CMD),
467 .flags = 0,
468 .data[0] = &mvm->fwrt.uats_table,
469 .len[0] = sizeof(mvm->fwrt.uats_table),
470 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
471 };
472 467
473 if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {468 if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
474 IWL_DEBUG_RADIO(mvm, "UATS feature is not supported\n");469 IWL_DEBUG_RADIO(mvm, "UATS feature is not supported\n");
475 return;470 return;
476 }471 }
477 472
478 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd.id,473 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
479 IWL_FW_CMD_VER_UNKNOWN);474 IWL_FW_CMD_VER_UNKNOWN);
480 if (cmd_ver != 1) {475 if (cmd_ver != 1) {
481 IWL_DEBUG_RADIO(mvm,476 IWL_DEBUG_RADIO(mvm,
@@ -486,10 +481,17 @@ static void iwl_mvm_uats_init(struct iwl_mvm *mvm) · 4 unmodified lines
486 481
487 iwl_uefi_get_uats_table(mvm->trans, &mvm->fwrt);482 iwl_uefi_get_uats_table(mvm->trans, &mvm->fwrt);
488 483
489 if (!mvm->fwrt.uats_valid)484 if (!mvm->fwrt.ap_type_cmd_valid)
490 return;485 return;
491 486
492 ret = iwl_mvm_send_cmd(mvm, &cmd);487 BUILD_BUG_ON(sizeof(mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map) !=
488 sizeof(cmd.mcc_to_ap_type_map));
489
490 memcpy(cmd.mcc_to_ap_type_map,
491 mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map,
492 sizeof(mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map));
493
494 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
493 if (ret < 0)495 if (ret < 0)
494 IWL_ERR(mvm, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",496 IWL_ERR(mvm, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",
495 ret);497 ret);
@@ -906,7 +908,7 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) · 410 unmodified lines
906 908
907int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)909int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
908{910{
909 union iwl_geo_tx_power_profiles_cmd geo_tx_cmd;911 union iwl_geo_tx_power_profiles_cmd geo_tx_cmd = {};
910 struct iwl_geo_tx_power_profiles_resp *resp;912 struct iwl_geo_tx_power_profiles_resp *resp;
911 u16 len;913 u16 len;
912 int ret;914 int ret;
@@ -958,7 +960,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) · 45 unmodified lines
958static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)960static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
959{961{
960 u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD);962 u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD);
961 union iwl_geo_tx_power_profiles_cmd cmd;963 union iwl_geo_tx_power_profiles_cmd cmd = {};
962 u16 len;964 u16 len;
963 u32 n_bands;965 u32 n_bands;
964 u32 n_profiles;966 u32 n_profiles;
@@ -1032,12 +1034,139 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) · 67 unmodified lines
1032 return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);1034 return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);
1033}1035}
1034 1036
1037static bool iwl_mvm_ppag_value_valid(struct iwl_fw_runtime *fwrt, int chain,
1038 int subband)
1039{
1040 s8 ppag_val = fwrt->ppag_chains[chain].subbands[subband];
1041
1042 if ((subband == 0 &&
1043 (ppag_val > IWL_PPAG_MAX_LB || ppag_val < IWL_PPAG_MIN_LB)) ||
1044 (subband != 0 &&
1045 (ppag_val > IWL_PPAG_MAX_HB || ppag_val < IWL_PPAG_MIN_HB))) {
1046 IWL_DEBUG_RADIO(fwrt, "Invalid PPAG value: %d\n", ppag_val);
1047 return false;
1048 }
1049 return true;
1050}
1051
1052static int iwl_mvm_fill_ppag_table(struct iwl_fw_runtime *fwrt,
1053 union iwl_ppag_table_cmd *cmd,
1054 int *cmd_size)
1055{
1056 u8 cmd_ver;
1057 int i, j, num_sub_bands;
1058 s8 *gain;
1059 bool send_ppag_always;
1060
1061 /* many firmware images for JF lie about this */
1062 if (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id) ==
1063 CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
1064 return -EOPNOTSUPP;
1065
1066 if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
1067 IWL_DEBUG_RADIO(fwrt,
1068 "PPAG capability not supported by FW, command not sent.\n");
1069 return -EINVAL;
1070 }
1071
1072 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
1073 WIDE_ID(PHY_OPS_GROUP,
1074 PER_PLATFORM_ANT_GAIN_CMD), 1);
1075 /*
1076 * Starting from ver 4, driver needs to send the PPAG CMD regardless
1077 * if PPAG is enabled/disabled or valid/invalid.
1078 */
1079 send_ppag_always = cmd_ver > 3;
1080
1081 /* Don't send PPAG if it is disabled */
1082 if (!send_ppag_always && !fwrt->ppag_flags) {
1083 IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
1084 return -EINVAL;
1085 }
1086
1087 IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
1088 if (cmd_ver == 1) {
1089 num_sub_bands = IWL_NUM_SUB_BANDS_V1;
1090 gain = cmd->v1.gain[0];
1091 *cmd_size = sizeof(cmd->v1);
1092 cmd->v1.flags =
1093 cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK);
1094 if (fwrt->ppag_bios_rev >= 1) {
1095 /* in this case FW supports revision 0 */
1096 IWL_DEBUG_RADIO(fwrt,
1097 "PPAG table rev is %d, send truncated table\n",
1098 fwrt->ppag_bios_rev);
1099 }
1100 } else if (cmd_ver == 5) {
1101 num_sub_bands = IWL_NUM_SUB_BANDS_V2;
1102 gain = cmd->v5.gain[0];
1103 *cmd_size = sizeof(cmd->v5);
1104 cmd->v5.flags =
1105 cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK);
1106 if (fwrt->ppag_bios_rev == 0) {
1107 /* in this case FW supports revisions 1,2 or 3 */
1108 IWL_DEBUG_RADIO(fwrt,
1109 "PPAG table rev is 0, send padded table\n");
1110 }
1111 } else if (cmd_ver == 7) {
1112 num_sub_bands = IWL_NUM_SUB_BANDS_V2;
1113 gain = cmd->v7.gain[0];
1114 *cmd_size = sizeof(cmd->v7);
1115 cmd->v7.ppag_config_info.hdr.table_source =
1116 fwrt->ppag_bios_source;
1117 cmd->v7.ppag_config_info.hdr.table_revision =
1118 fwrt->ppag_bios_rev;
1119 cmd->v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags);
1120 } else {
1121 IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
1122 return -EINVAL;
1123 }
1124
1125 /* ppag mode */
1126 IWL_DEBUG_RADIO(fwrt,
1127 "PPAG MODE bits were read from bios: %d\n",
1128 fwrt->ppag_flags);
1129
1130 if (cmd_ver == 1 &&
1131 !fw_has_capa(&fwrt->fw->ucode_capa,
1132 IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) {
1133 cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
1134 IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
1135 } else {
1136 IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
1137 }
1138
1139 /* The 'flags' field is the same in v1 and v5 so we can just
1140 * use v1 to access it.
1141 */
1142 IWL_DEBUG_RADIO(fwrt,
1143 "PPAG MODE bits going to be sent: %d\n",
1144 (cmd_ver < 7) ? le32_to_cpu(cmd->v1.flags) :
1145 le32_to_cpu(cmd->v7.ppag_config_info.value));
1146
1147 for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
1148 for (j = 0; j < num_sub_bands; j++) {
1149 if (!send_ppag_always &&
1150 !iwl_mvm_ppag_value_valid(fwrt, i, j))
1151 return -EINVAL;
1152
1153 gain[i * num_sub_bands + j] =
1154 fwrt->ppag_chains[i].subbands[j];
1155 IWL_DEBUG_RADIO(fwrt,
1156 "PPAG table: chain[%d] band[%d]: gain = %d\n",
1157 i, j, gain[i * num_sub_bands + j]);
1158 }
1159 }
1160
1161 return 0;
1162}
1163
1035int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)1164int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
1036{1165{
1037 union iwl_ppag_table_cmd cmd;1166 union iwl_ppag_table_cmd cmd;
1038 int ret, cmd_size;1167 int ret, cmd_size;
1039 1168
1040 ret = iwl_fill_ppag_table(&mvm->fwrt, &cmd, &cmd_size);1169 ret = iwl_mvm_fill_ppag_table(&mvm->fwrt, &cmd, &cmd_size);
1041 /* Not supporting PPAG table is a valid scenario */1170 /* Not supporting PPAG table is a valid scenario */
1042 if (ret < 0)1171 if (ret < 0)
1043 return 0;1172 return 0;
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c+4−3
@@ -6229,9 +6229,10 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, · 6228 unmodified lines
6229 ret = wait_event_timeout(mvm->rx_sync_waitq,6229 ret = wait_event_timeout(mvm->rx_sync_waitq,
6230 READ_ONCE(mvm->queue_sync_state) == 0,6230 READ_ONCE(mvm->queue_sync_state) == 0,
6231 SYNC_RX_QUEUE_TIMEOUT);6231 SYNC_RX_QUEUE_TIMEOUT);
6232 WARN_ONCE(!ret, "queue sync: failed to sync, state is 0x%lx, cookie %d\n",6232 IWL_FW_CHECK(mvm, !ret,
6233 mvm->queue_sync_state,6233 "queue sync: failed to sync, state is 0x%lx, cookie %d\n",
6234 mvm->queue_sync_cookie);6234 mvm->queue_sync_state,
6235 mvm->queue_sync_cookie);
6235 }6236 }
6236 6237
6237out:6238out:
drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c+0−46
@@ -121,52 +121,6 @@ struct iwl_mvm_sta_key_update_data { · 120 unmodified lines
121 int err;121 int err;
122};122};
123 123
124static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,
125 struct ieee80211_vif *vif,
126 struct ieee80211_sta *sta,
127 struct ieee80211_key_conf *key,
128 void *_data)
129{
130 u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
131 struct iwl_mvm_sta_key_update_data *data = _data;
132 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
133 struct iwl_sec_key_cmd cmd = {
134 .action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
135 .u.modify.old_sta_mask = cpu_to_le32(data->old_sta_mask),
136 .u.modify.new_sta_mask = cpu_to_le32(data->new_sta_mask),
137 .u.modify.key_id = cpu_to_le32(key->keyidx),
138 .u.modify.key_flags =
139 cpu_to_le32(iwl_mvm_get_sec_flags(mvm, vif, sta, key)),
140 };
141 int err;
142
143 /* only need to do this for pairwise keys (link_id == -1) */
144 if (sta != data->sta || key->link_id >= 0)
145 return;
146
147 err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
148
149 if (err)
150 data->err = err;
151}
152
153int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
154 struct ieee80211_vif *vif,
155 struct ieee80211_sta *sta,
156 u32 old_sta_mask,
157 u32 new_sta_mask)
158{
159 struct iwl_mvm_sta_key_update_data data = {
160 .sta = sta,
161 .old_sta_mask = old_sta_mask,
162 .new_sta_mask = new_sta_mask,
163 };
164
165 ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
166 &data);
167 return data.err;
168}
169
170static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,124static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
171 u32 key_flags, u32 keyidx, u32 flags)125 u32 key_flags, u32 keyidx, u32 flags)
172{126{
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c+9−9
@@ -6,7 +6,7 @@ · 5 unmodified lines
6 6
7static void iwl_mvm_mld_set_he_support(struct iwl_mvm *mvm,7static void iwl_mvm_mld_set_he_support(struct iwl_mvm *mvm,
8 struct ieee80211_vif *vif,8 struct ieee80211_vif *vif,
9 struct iwl_mac_config_cmd *cmd,9 struct iwl_mac_config_cmd_v3 *cmd,
10 int cmd_ver)10 int cmd_ver)
11{11{
12 if (vif->type == NL80211_IFTYPE_AP) {12 if (vif->type == NL80211_IFTYPE_AP) {
@@ -24,7 +24,7 @@ static void iwl_mvm_mld_set_he_support(struct iwl_mvm *mvm, · 11 unmodified lines
24 24
25static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,25static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
26 struct ieee80211_vif *vif,26 struct ieee80211_vif *vif,
27 struct iwl_mac_config_cmd *cmd,27 struct iwl_mac_config_cmd_v3 *cmd,
28 u32 action)28 u32 action)
29{29{
30 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);30 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -83,7 +83,7 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm, · 52 unmodified lines
83}83}
84 84
85static int iwl_mvm_mld_mac_ctxt_send_cmd(struct iwl_mvm *mvm,85static int iwl_mvm_mld_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
86 struct iwl_mac_config_cmd *cmd)86 struct iwl_mac_config_cmd_v3 *cmd)
87{87{
88 int ret = iwl_mvm_send_cmd_pdu(mvm,88 int ret = iwl_mvm_send_cmd_pdu(mvm,
89 WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),89 WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),
@@ -98,7 +98,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, · 8 unmodified lines
98 struct ieee80211_vif *vif,98 struct ieee80211_vif *vif,
99 u32 action, bool force_assoc_off)99 u32 action, bool force_assoc_off)
100{100{
101 struct iwl_mac_config_cmd cmd = {};101 struct iwl_mac_config_cmd_v3 cmd = {};
102 102
103 WARN_ON(vif->type != NL80211_IFTYPE_STATION);103 WARN_ON(vif->type != NL80211_IFTYPE_STATION);
104 104
@@ -151,7 +151,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, · 46 unmodified lines
151 struct ieee80211_vif *vif,151 struct ieee80211_vif *vif,
152 u32 action)152 u32 action)
153{153{
154 struct iwl_mac_config_cmd cmd = {};154 struct iwl_mac_config_cmd_v3 cmd = {};
155 155
156 WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);156 WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
157 157
@@ -170,7 +170,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm, · 12 unmodified lines
170 struct ieee80211_vif *vif,170 struct ieee80211_vif *vif,
171 u32 action)171 u32 action)
172{172{
173 struct iwl_mac_config_cmd cmd = {};173 struct iwl_mac_config_cmd_v3 cmd = {};
174 174
175 WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);175 WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
176 176
@@ -187,7 +187,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm, · 10 unmodified lines
187 struct ieee80211_vif *vif,187 struct ieee80211_vif *vif,
188 u32 action)188 u32 action)
189{189{
190 struct iwl_mac_config_cmd cmd = {};190 struct iwl_mac_config_cmd_v3 cmd = {};
191 191
192 WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);192 WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
193 193
@@ -210,7 +210,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_ap_go(struct iwl_mvm *mvm, · 16 unmodified lines
210 u32 action)210 u32 action)
211{211{
212 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);212 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
213 struct iwl_mac_config_cmd cmd = {};213 struct iwl_mac_config_cmd_v3 cmd = {};
214 214
215 WARN_ON(vif->type != NL80211_IFTYPE_AP);215 WARN_ON(vif->type != NL80211_IFTYPE_AP);
216 216
@@ -286,7 +286,7 @@ int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm, · 69 unmodified lines
286int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)286int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
287{287{
288 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);288 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
289 struct iwl_mac_config_cmd cmd = {289 struct iwl_mac_config_cmd_v3 cmd = {
290 .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),290 .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
291 .id_and_color = cpu_to_le32(mvmvif->id),291 .id_and_color = cpu_to_le32(mvmvif->id),
292 };292 };
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c+0−132
@@ -886,133 +886,6 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 885 unmodified lines
886 return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);886 return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
887}887}
888 888
889static int
890iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
891 struct ieee80211_vif *vif,
892 u16 old_links, u16 new_links,
893 struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
894{
895 struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
896 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
897 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
898 u16 removed = old_links & ~new_links;
899 u16 added = new_links & ~old_links;
900 int err, i;
901
902 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
903 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
904 break;
905
906 if (!(added & BIT(i)))
907 continue;
908 new_link[i] = kzalloc_obj(*new_link[i]);
909 if (!new_link[i]) {
910 err = -ENOMEM;
911 goto free;
912 }
913
914 new_link[i]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
915 iwl_mvm_init_link(new_link[i]);
916 }
917
918 mutex_lock(&mvm->mutex);
919
920 /* If we're in RESTART flow, the default link wasn't added in
921 * drv_add_interface(), and link[0] doesn't point to it.
922 */
923 if (old_links == 0 && !test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
924 &mvm->status)) {
925 err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
926 if (err)
927 goto out_err;
928 mvmvif->link[0] = NULL;
929 }
930
931 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
932 if (removed & BIT(i)) {
933 struct ieee80211_bss_conf *link_conf = old[i];
934
935 err = iwl_mvm_disable_link(mvm, vif, link_conf);
936 if (err)
937 goto out_err;
938 kfree(mvmvif->link[i]);
939 mvmvif->link[i] = NULL;
940 } else if (added & BIT(i)) {
941 struct ieee80211_bss_conf *link_conf;
942
943 link_conf = link_conf_dereference_protected(vif, i);
944 if (WARN_ON(!link_conf))
945 continue;
946
947 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
948 &mvm->status))
949 mvmvif->link[i] = new_link[i];
950 new_link[i] = NULL;
951 err = iwl_mvm_add_link(mvm, vif, link_conf);
952 if (err)
953 goto out_err;
954 }
955 }
956
957 err = 0;
958 if (new_links == 0) {
959 mvmvif->link[0] = &mvmvif->deflink;
960 err = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
961 }
962
963out_err:
964 /* we really don't have a good way to roll back here ... */
965 mutex_unlock(&mvm->mutex);
966
967free:
968 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++)
969 kfree(new_link[i]);
970 return err;
971}
972
973static int
974iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
975 struct ieee80211_vif *vif,
976 struct ieee80211_sta *sta,
977 u16 old_links, u16 new_links)
978{
979 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
980
981 guard(mvm)(mvm);
982 return iwl_mvm_mld_update_sta_links(mvm, vif, sta, old_links, new_links);
983}
984
985static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw,
986 struct ieee80211_vif *vif,
987 u16 desired_links)
988{
989 int n_links = hweight16(desired_links);
990
991 if (n_links <= 1)
992 return true;
993
994 WARN_ON(1);
995 return false;
996}
997
998static enum ieee80211_neg_ttlm_res
999iwl_mvm_mld_can_neg_ttlm(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1000 struct ieee80211_neg_ttlm *neg_ttlm)
1001{
1002 u16 map;
1003 u8 i;
1004
1005 /* Verify all TIDs are mapped to the same links set */
1006 map = neg_ttlm->downlink[0];
1007 for (i = 0; i < IEEE80211_TTLM_NUM_TIDS; i++) {
1008 if (neg_ttlm->downlink[i] != neg_ttlm->uplink[i] ||
1009 neg_ttlm->uplink[i] != map)
1010 return NEG_TTLM_RES_REJECT;
1011 }
1012
1013 return NEG_TTLM_RES_ACCEPT;
1014}
1015
1016const struct ieee80211_ops iwl_mvm_mld_hw_ops = {889const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
1017 .tx = iwl_mvm_mac_tx,890 .tx = iwl_mvm_mac_tx,
1018 .wake_tx_queue = iwl_mvm_mac_wake_tx_queue,891 .wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
@@ -1102,9 +975,4 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = { · 83 unmodified lines
1102 .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,975 .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
1103#endif976#endif
1104 .set_hw_timestamp = iwl_mvm_set_hw_timestamp,977 .set_hw_timestamp = iwl_mvm_set_hw_timestamp,
1105
1106 .change_vif_links = iwl_mvm_mld_change_vif_links,
1107 .change_sta_links = iwl_mvm_mld_change_sta_links,
1108 .can_activate_links = iwl_mvm_mld_can_activate_links,
1109 .can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm,
1110};978};
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c+3−288
@@ -20,7 +20,7 @@ u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta, · 19 unmodified lines
20}20}
21 21
22static int iwl_mvm_mld_send_sta_cmd(struct iwl_mvm *mvm,22static int iwl_mvm_mld_send_sta_cmd(struct iwl_mvm *mvm,
23 struct iwl_sta_cfg_cmd *cmd)23 struct iwl_sta_cfg_cmd_v2 *cmd)
24{24{
25 u32 cmd_id = WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD);25 u32 cmd_id = WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD);
26 int cmd_len = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) > 1 ?26 int cmd_len = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) > 1 ?
@@ -41,7 +41,7 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm, · 14 unmodified lines
41 struct iwl_mvm_int_sta *sta,41 struct iwl_mvm_int_sta *sta,
42 const u8 *addr, int link_id)42 const u8 *addr, int link_id)
43{43{
44 struct iwl_sta_cfg_cmd cmd;44 struct iwl_sta_cfg_cmd_v2 cmd;
45 45
46 lockdep_assert_held(&mvm->mutex);46 lockdep_assert_held(&mvm->mutex);
47 47
@@ -416,7 +416,7 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta, · 368 unmodified lines
416 struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);416 struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
417 struct iwl_mvm_vif_link_info *link_info =417 struct iwl_mvm_vif_link_info *link_info =
418 mvm_vif->link[link_conf->link_id];418 mvm_vif->link[link_conf->link_id];
419 struct iwl_sta_cfg_cmd cmd = {419 struct iwl_sta_cfg_cmd_v2 cmd = {
420 .sta_id = cpu_to_le32(mvm_link_sta->sta_id),420 .sta_id = cpu_to_le32(mvm_link_sta->sta_id),
421 .station_type = cpu_to_le32(mvm_sta->sta_type),421 .station_type = cpu_to_le32(mvm_sta->sta_type),
422 };422 };
@@ -913,288 +913,3 @@ void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm, · 490 unmodified lines
913 913
914 rcu_read_unlock();914 rcu_read_unlock();
915}915}
916
917static int iwl_mvm_mld_update_sta_queues(struct iwl_mvm *mvm,
918 struct ieee80211_sta *sta,
919 u32 old_sta_mask,
920 u32 new_sta_mask)
921{
922 struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
923 struct iwl_scd_queue_cfg_cmd cmd = {
924 .operation = cpu_to_le32(IWL_SCD_QUEUE_MODIFY),
925 .u.modify.old_sta_mask = cpu_to_le32(old_sta_mask),
926 .u.modify.new_sta_mask = cpu_to_le32(new_sta_mask),
927 };
928 struct iwl_host_cmd hcmd = {
929 .id = WIDE_ID(DATA_PATH_GROUP, SCD_QUEUE_CONFIG_CMD),
930 .len[0] = sizeof(cmd),
931 .data[0] = &cmd
932 };
933 int tid;
934 int ret;
935
936 lockdep_assert_held(&mvm->mutex);
937
938 for (tid = 0; tid <= IWL_MAX_TID_COUNT; tid++) {
939 struct iwl_mvm_tid_data *tid_data = &mvm_sta->tid_data[tid];
940 int txq_id = tid_data->txq_id;
941
942 if (txq_id == IWL_MVM_INVALID_QUEUE)
943 continue;
944
945 if (tid == IWL_MAX_TID_COUNT)
946 cmd.u.modify.tid = cpu_to_le32(IWL_MGMT_TID);
947 else
948 cmd.u.modify.tid = cpu_to_le32(tid);
949
950 ret = iwl_mvm_send_cmd(mvm, &hcmd);
951 if (ret)
952 return ret;
953 }
954
955 return 0;
956}
957
958static int iwl_mvm_mld_update_sta_baids(struct iwl_mvm *mvm,
959 u32 old_sta_mask,
960 u32 new_sta_mask)
961{
962 struct iwl_rx_baid_cfg_cmd cmd = {
963 .action = cpu_to_le32(IWL_RX_BAID_ACTION_MODIFY),
964 .modify.old_sta_id_mask = cpu_to_le32(old_sta_mask),
965 .modify.new_sta_id_mask = cpu_to_le32(new_sta_mask),
966 };
967 u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);
968 int baid;
969
970 /* mac80211 will remove sessions later, but we ignore all that */
971 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
972 return 0;
973
974 BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));
975
976 for (baid = 0; baid < ARRAY_SIZE(mvm->baid_map); baid++) {
977 struct iwl_mvm_baid_data *data;
978 int ret;
979
980 data = rcu_dereference_protected(mvm->baid_map[baid],
981 lockdep_is_held(&mvm->mutex));
982 if (!data)
983 continue;
984
985 if (!(data->sta_mask & old_sta_mask))
986 continue;
987
988 WARN_ONCE(data->sta_mask != old_sta_mask,
989 "BAID data for %d corrupted - expected 0x%x found 0x%x\n",
990 baid, old_sta_mask, data->sta_mask);
991
992 cmd.modify.tid = cpu_to_le32(data->tid);
993
994 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_SEND_IN_RFKILL,
995 sizeof(cmd), &cmd);
996 data->sta_mask = new_sta_mask;
997 if (ret)
998 return ret;
999 }
1000
1001 return 0;
1002}
1003
1004static int iwl_mvm_mld_update_sta_resources(struct iwl_mvm *mvm,
1005 struct ieee80211_vif *vif,
1006 struct ieee80211_sta *sta,
1007 u32 old_sta_mask,
1008 u32 new_sta_mask)
1009{
1010 int ret;
1011
1012 ret = iwl_mvm_mld_update_sta_queues(mvm, sta,
1013 old_sta_mask,
1014 new_sta_mask);
1015 if (ret)
1016 return ret;
1017
1018 ret = iwl_mvm_mld_update_sta_keys(mvm, vif, sta,
1019 old_sta_mask,
1020 new_sta_mask);
1021 if (ret)
1022 return ret;
1023
1024 return iwl_mvm_mld_update_sta_baids(mvm, old_sta_mask, new_sta_mask);
1025}
1026
1027int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
1028 struct ieee80211_vif *vif,
1029 struct ieee80211_sta *sta,
1030 u16 old_links, u16 new_links)
1031{
1032 struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
1033 struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
1034 struct iwl_mvm_link_sta *mvm_sta_link;
1035 struct iwl_mvm_vif_link_info *mvm_vif_link;
1036 unsigned long links_to_add = ~old_links & new_links;
1037 unsigned long links_to_rem = old_links & ~new_links;
1038 unsigned long old_links_long = old_links;
1039 u32 current_sta_mask = 0, sta_mask_added = 0, sta_mask_to_rem = 0;
1040 unsigned long link_sta_added_to_fw = 0, link_sta_allocated = 0;
1041 unsigned int link_id;
1042 int ret;
1043
1044 lockdep_assert_wiphy(mvm->hw->wiphy);
1045 lockdep_assert_held(&mvm->mutex);
1046
1047 for_each_set_bit(link_id, &old_links_long,
1048 IEEE80211_MLD_MAX_NUM_LINKS) {
1049 mvm_sta_link =
1050 rcu_dereference_protected(mvm_sta->link[link_id],
1051 lockdep_is_held(&mvm->mutex));
1052
1053 if (WARN_ON(!mvm_sta_link)) {
1054 ret = -EINVAL;
1055 goto err;
1056 }
1057
1058 current_sta_mask |= BIT(mvm_sta_link->sta_id);
1059 if (links_to_rem & BIT(link_id))
1060 sta_mask_to_rem |= BIT(mvm_sta_link->sta_id);
1061 }
1062
1063 if (sta_mask_to_rem) {
1064 ret = iwl_mvm_mld_update_sta_resources(mvm, vif, sta,
1065 current_sta_mask,
1066 current_sta_mask &
1067 ~sta_mask_to_rem);
1068 if (WARN_ON(ret))
1069 goto err;
1070
1071 current_sta_mask &= ~sta_mask_to_rem;
1072 }
1073
1074 for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) {
1075 mvm_sta_link =
1076 rcu_dereference_protected(mvm_sta->link[link_id],
1077 lockdep_is_held(&mvm->mutex));
1078 mvm_vif_link = mvm_vif->link[link_id];
1079
1080 if (WARN_ON(!mvm_sta_link || !mvm_vif_link)) {
1081 ret = -EINVAL;
1082 goto err;
1083 }
1084
1085 ret = iwl_mvm_mld_rm_sta_from_fw(mvm, mvm_sta_link->sta_id);
1086 if (WARN_ON(ret))
1087 goto err;
1088
1089 if (vif->type == NL80211_IFTYPE_STATION)
1090 mvm_vif_link->ap_sta_id = IWL_INVALID_STA;
1091
1092 iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_sta_link, link_id);
1093 }
1094
1095 for_each_set_bit(link_id, &links_to_add, IEEE80211_MLD_MAX_NUM_LINKS) {
1096 struct ieee80211_bss_conf *link_conf =
1097 link_conf_dereference_protected(vif, link_id);
1098 struct ieee80211_link_sta *link_sta =
1099 link_sta_dereference_protected(sta, link_id);
1100 mvm_vif_link = mvm_vif->link[link_id];
1101
1102 if (WARN_ON(!mvm_vif_link || !link_conf || !link_sta)) {
1103 ret = -EINVAL;
1104 goto err;
1105 }
1106
1107 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
1108 struct iwl_mvm_link_sta *mvm_link_sta =
1109 rcu_dereference_protected(mvm_sta->link[link_id],
1110 lockdep_is_held(&mvm->mutex));
1111 u32 sta_id;
1112
1113 if (WARN_ON(!mvm_link_sta)) {
1114 ret = -EINVAL;
1115 goto err;
1116 }
1117
1118 sta_id = mvm_link_sta->sta_id;
1119
1120 rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
1121 rcu_assign_pointer(mvm->fw_id_to_link_sta[sta_id],
1122 link_sta);
1123 } else {
1124 if (WARN_ON(mvm_sta->link[link_id])) {
1125 ret = -EINVAL;
1126 goto err;
1127 }
1128 ret = iwl_mvm_mld_alloc_sta_link(mvm, vif, sta,
1129 link_id);
1130 if (WARN_ON(ret))
1131 goto err;
1132 }
1133
1134 link_sta->agg.max_rc_amsdu_len = 1;
1135 ieee80211_sta_recalc_aggregates(sta);
1136
1137 mvm_sta_link =
1138 rcu_dereference_protected(mvm_sta->link[link_id],
1139 lockdep_is_held(&mvm->mutex));
1140
1141 if (WARN_ON(!mvm_sta_link)) {
1142 ret = -EINVAL;
1143 goto err;
1144 }
1145
1146 if (vif->type == NL80211_IFTYPE_STATION)
1147 iwl_mvm_mld_set_ap_sta_id(sta, mvm_vif_link,
1148 mvm_sta_link);
1149
1150 link_sta_allocated |= BIT(link_id);
1151
1152 sta_mask_added |= BIT(mvm_sta_link->sta_id);
1153
1154 ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif, link_sta, link_conf,
1155 mvm_sta_link);
1156 if (WARN_ON(ret))
1157 goto err;
1158
1159 link_sta_added_to_fw |= BIT(link_id);
1160
1161 iwl_mvm_rs_add_sta_link(mvm, mvm_sta_link);
1162
1163 iwl_mvm_rs_rate_init(mvm, vif, sta, link_conf, link_sta,
1164 link_conf->chanreq.oper.chan->band);
1165 }
1166
1167 if (sta_mask_added) {
1168 ret = iwl_mvm_mld_update_sta_resources(mvm, vif, sta,
1169 current_sta_mask,
1170 current_sta_mask |
1171 sta_mask_added);
1172 if (WARN_ON(ret))
1173 goto err;
1174 }
1175
1176 return 0;
1177
1178err:
1179 /* remove all already allocated stations in FW */
1180 for_each_set_bit(link_id, &link_sta_added_to_fw,
1181 IEEE80211_MLD_MAX_NUM_LINKS) {
1182 mvm_sta_link =
1183 rcu_dereference_protected(mvm_sta->link[link_id],
1184 lockdep_is_held(&mvm->mutex));
1185
1186 iwl_mvm_mld_rm_sta_from_fw(mvm, mvm_sta_link->sta_id);
1187 }
1188
1189 /* remove all already allocated station links in driver */
1190 for_each_set_bit(link_id, &link_sta_allocated,
1191 IEEE80211_MLD_MAX_NUM_LINKS) {
1192 mvm_sta_link =
1193 rcu_dereference_protected(mvm_sta->link[link_id],
1194 lockdep_is_held(&mvm->mutex));
1195
1196 iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_sta_link, link_id);
1197 }
1198
1199 return ret;
1200}
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h+0−5
@@ -2450,11 +2450,6 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm, · 2449 unmodified lines
2450 struct ieee80211_vif *vif,2450 struct ieee80211_vif *vif,
2451 struct iwl_mvm_vif_link_info *link,2451 struct iwl_mvm_vif_link_info *link,
2452 unsigned int link_id);2452 unsigned int link_id);
2453int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
2454 struct ieee80211_vif *vif,
2455 struct ieee80211_sta *sta,
2456 u32 old_sta_mask,
2457 u32 new_sta_mask);
2458int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,2453int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
2459 struct ieee80211_key_conf *keyconf);2454 struct ieee80211_key_conf *keyconf);
2460u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,2455u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
drivers/net/wireless/intel/iwlwifi/mvm/ptp.c+3−1
@@ -304,7 +304,9 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm) · 303 unmodified lines
304 IWL_ERR(mvm, "Failed to register PHC clock (%ld)\n",304 IWL_ERR(mvm, "Failed to register PHC clock (%ld)\n",
305 PTR_ERR(mvm->ptp_data.ptp_clock));305 PTR_ERR(mvm->ptp_data.ptp_clock));
306 mvm->ptp_data.ptp_clock = NULL;306 mvm->ptp_data.ptp_clock = NULL;
307 } else if (mvm->ptp_data.ptp_clock) {307 } else if (!mvm->ptp_data.ptp_clock) {
308 IWL_DEBUG_INFO(mvm, "PTP module unavailable on this kernel\n");
309 } else {
308 IWL_DEBUG_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",310 IWL_DEBUG_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
309 mvm->ptp_data.ptp_clock_info.name,311 mvm->ptp_data.ptp_clock_info.name,
310 ptp_clock_index(mvm->ptp_data.ptp_clock));312 ptp_clock_index(mvm->ptp_data.ptp_clock));
drivers/net/wireless/intel/iwlwifi/mvm/sta.h+0−4
@@ -637,10 +637,6 @@ void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm, · 636 unmodified lines
637 struct iwl_mvm_link_sta *mvm_sta_link,637 struct iwl_mvm_link_sta *mvm_sta_link,
638 unsigned int link_id);638 unsigned int link_id);
639int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id);639int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id);
640int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
641 struct ieee80211_vif *vif,
642 struct ieee80211_sta *sta,
643 u16 old_links, u16 new_links);
644u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,640u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
645 int filter_link_id);641 int filter_link_id);
646int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,642int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
drivers/net/wireless/intel/iwlwifi/mvm/tdls.c+3−3
@@ -234,7 +234,7 @@ void iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) · 233 unmodified lines
234 * Also convert TU to msec.234 * Also convert TU to msec.
235 */235 */
236 delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);236 delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
237 mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,237 mod_delayed_work(system_percpu_wq, &mvm->tdls_cs.dwork,
238 msecs_to_jiffies(delay));238 msecs_to_jiffies(delay));
239 239
240 iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_ACTIVE);240 iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_ACTIVE);
@@ -548,7 +548,7 @@ iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw, · 307 unmodified lines
548 */548 */
549 delay = 2 * TU_TO_MS(vif->bss_conf.dtim_period *549 delay = 2 * TU_TO_MS(vif->bss_conf.dtim_period *
550 vif->bss_conf.beacon_int);550 vif->bss_conf.beacon_int);
551 mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,551 mod_delayed_work(system_percpu_wq, &mvm->tdls_cs.dwork,
552 msecs_to_jiffies(delay));552 msecs_to_jiffies(delay));
553 return 0;553 return 0;
554}554}
@@ -659,6 +659,6 @@ retry: · 104 unmodified lines
659 /* register a timeout in case we don't succeed in switching */659 /* register a timeout in case we don't succeed in switching */
660 delay = vif->bss_conf.dtim_period * vif->bss_conf.beacon_int *660 delay = vif->bss_conf.dtim_period * vif->bss_conf.beacon_int *
661 1024 / 1000;661 1024 / 1000;
662 mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,662 mod_delayed_work(system_percpu_wq, &mvm->tdls_cs.dwork,
663 msecs_to_jiffies(delay));663 msecs_to_jiffies(delay));
664}664}
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c+10−3
@@ -95,7 +95,9 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave) · 94 unmodified lines
95 CSR_GP_CNTRL_REG_FLAG_INIT_DONE);95 CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
96}96}
97 97
98void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)98static void
99_iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans,
100 bool dump_on_timeout)
99{101{
100 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);102 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
101 int ret;103 int ret;
@@ -133,7 +135,7 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans) · 31 unmodified lines
133 "timeout waiting for FW reset ACK (inta_hw=0x%x, reset_done %d)\n",135 "timeout waiting for FW reset ACK (inta_hw=0x%x, reset_done %d)\n",
134 inta_hw, reset_done);136 inta_hw, reset_done);
135 137
136 if (!reset_done) {138 if (!reset_done && dump_on_timeout) {
137 struct iwl_fw_error_dump_mode mode = {139 struct iwl_fw_error_dump_mode mode = {
138 .type = IWL_ERR_TYPE_RESET_HS_TIMEOUT,140 .type = IWL_ERR_TYPE_RESET_HS_TIMEOUT,
139 .context = IWL_ERR_CONTEXT_FROM_OPMODE,141 .context = IWL_ERR_CONTEXT_FROM_OPMODE,
@@ -147,6 +149,11 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans) · 7 unmodified lines
147 trans_pcie->fw_reset_state = FW_RESET_IDLE;149 trans_pcie->fw_reset_state = FW_RESET_IDLE;
148}150}
149 151
152void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
153{
154 _iwl_trans_pcie_fw_reset_handshake(trans, false);
155}
156
150static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)157static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
151{158{
152 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);159 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -163,7 +170,7 @@ static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) · 10 unmodified lines
163 * should assume that the firmware is already dead.170 * should assume that the firmware is already dead.
164 */171 */
165 trans->state = IWL_TRANS_NO_FW;172 trans->state = IWL_TRANS_NO_FW;
166 iwl_trans_pcie_fw_reset_handshake(trans);173 _iwl_trans_pcie_fw_reset_handshake(trans, true);
167 }174 }
168 175
169 trans_pcie->is_down = true;176 trans_pcie->is_down = true;
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c+1−1
@@ -3197,7 +3197,7 @@ static ssize_t iwl_dbgfs_reset_write(struct file *file, · 3196 unmodified lines
3197 if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status))3197 if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status))
3198 return -EINVAL;3198 return -EINVAL;
3199 if (mode == IWL_RESET_MODE_TOP_RESET) {3199 if (mode == IWL_RESET_MODE_TOP_RESET) {
3200 if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)3200 if (!iwl_trans_is_top_reset_supported(trans))
3201 return -EINVAL;3201 return -EINVAL;
3202 trans->request_top_reset = 1;3202 trans->request_top_reset = 1;
3203 }3203 }
drivers/net/wireless/mediatek/mt76/channel.c+25−14
@@ -88,6 +88,9 @@ void mt76_change_chanctx(struct ieee80211_hw *hw, · 87 unmodified lines
88 IEEE80211_CHANCTX_CHANGE_RADAR)))88 IEEE80211_CHANCTX_CHANGE_RADAR)))
89 return;89 return;
90 90
91 if (phy->roc_vif)
92 mt76_abort_roc(phy);
93
91 cancel_delayed_work_sync(&phy->mac_work);94 cancel_delayed_work_sync(&phy->mac_work);
92 95
93 mutex_lock(&dev->mutex);96 mutex_lock(&dev->mutex);
@@ -155,8 +158,6 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw, · 61 unmodified lines
155{158{
156 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv;159 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv;
157 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;160 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
158 struct mt76_vif_data *mvif = mlink->mvif;
159 int link_id = link_conf->link_id;
160 struct mt76_phy *phy = ctx->phy;161 struct mt76_phy *phy = ctx->phy;
161 struct mt76_dev *dev = phy->dev;162 struct mt76_dev *dev = phy->dev;
162 163
@@ -173,15 +174,8 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw, · 10 unmodified lines
173 if (!mlink)174 if (!mlink)
174 goto out;175 goto out;
175 176
176 if (mlink != (struct mt76_vif_link *)vif->drv_priv)
177 rcu_assign_pointer(mvif->link[link_id], NULL);
178
179 dev->drv->vif_link_remove(phy, vif, link_conf, mlink);177 dev->drv->vif_link_remove(phy, vif, link_conf, mlink);
180 mlink->ctx = NULL;178 mlink->ctx = NULL;
181
182 if (mlink != (struct mt76_vif_link *)vif->drv_priv)
183 kfree_rcu(mlink, rcu_head);
184
185out:179out:
186 mutex_unlock(&dev->mutex);180 mutex_unlock(&dev->mutex);
187}181}
@@ -254,6 +248,8 @@ skip_link_replace: · 66 unmodified lines
254 continue;248 continue;
255 249
256 mlink->ctx = vifs->new_ctx;250 mlink->ctx = vifs->new_ctx;
251 if (mlink->beacon_mon_interval)
252 WRITE_ONCE(mlink->beacon_mon_last, jiffies);
257 }253 }
258 254
259out:255out:
@@ -324,9 +320,11 @@ void mt76_roc_complete(struct mt76_phy *phy) · 64 unmodified lines
324 320
325 if (mlink)321 if (mlink)
326 mlink->mvif->roc_phy = NULL;322 mlink->mvif->roc_phy = NULL;
327 if (phy->main_chandef.chan &&323 if (phy->chanctx && phy->main_chandef.chan && phy->offchannel &&
328 !test_bit(MT76_MCU_RESET, &dev->phy.state))324 !test_bit(MT76_MCU_RESET, &dev->phy.state)) {
329 mt76_set_channel(phy, &phy->main_chandef, false);325 __mt76_set_channel(phy, &phy->main_chandef, false);
326 mt76_offchannel_notify(phy, false);
327 }
330 mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link);328 mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link);
331 phy->roc_vif = NULL;329 phy->roc_vif = NULL;
332 phy->roc_link = NULL;330 phy->roc_link = NULL;
@@ -364,12 +362,15 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 31 unmodified lines
364 struct mt76_phy *phy = hw->priv;362 struct mt76_phy *phy = hw->priv;
365 struct mt76_dev *dev = phy->dev;363 struct mt76_dev *dev = phy->dev;
366 struct mt76_vif_link *mlink;364 struct mt76_vif_link *mlink;
365 bool offchannel;
367 int ret = 0;366 int ret = 0;
368 367
369 phy = dev->band_phys[chan->band];368 phy = dev->band_phys[chan->band];
370 if (!phy)369 if (!phy)
371 return -EINVAL;370 return -EINVAL;
372 371
372 cancel_delayed_work_sync(&phy->mac_work);
373
373 mutex_lock(&dev->mutex);374 mutex_lock(&dev->mutex);
374 375
375 if (phy->roc_vif || dev->scan.phy == phy ||376 if (phy->roc_vif || dev->scan.phy == phy ||
@@ -387,8 +388,18 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 11 unmodified lines
387 mlink->mvif->roc_phy = phy;388 mlink->mvif->roc_phy = phy;
388 phy->roc_vif = vif;389 phy->roc_vif = vif;
389 phy->roc_link = mlink;390 phy->roc_link = mlink;
390 cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);391
391 mt76_set_channel(phy, &chandef, true);392 offchannel = mt76_offchannel_chandef(phy, chan, &chandef);
393 if (offchannel)
394 mt76_offchannel_notify(phy, true);
395 ret = __mt76_set_channel(phy, &chandef, offchannel);
396 if (ret) {
397 mlink->mvif->roc_phy = NULL;
398 phy->roc_vif = NULL;
399 phy->roc_link = NULL;
400 mt76_put_vif_phy_link(phy, vif, mlink);
401 goto out;
402 }
392 ieee80211_ready_on_channel(hw);403 ieee80211_ready_on_channel(hw);
393 ieee80211_queue_delayed_work(phy->hw, &phy->roc_work,404 ieee80211_queue_delayed_work(phy->hw, &phy->roc_work,
394 msecs_to_jiffies(duration));405 msecs_to_jiffies(duration));
drivers/net/wireless/mediatek/mt76/dma.c+25−8
@@ -6,6 +6,7 @@ · 5 unmodified lines
6#include <linux/dma-mapping.h>6#include <linux/dma-mapping.h>
7#include "mt76.h"7#include "mt76.h"
8#include "dma.h"8#include "dma.h"
9#include "mt76_connac.h"
9 10
10static struct mt76_txwi_cache *11static struct mt76_txwi_cache *
11mt76_alloc_txwi(struct mt76_dev *dev)12mt76_alloc_txwi(struct mt76_dev *dev)
@@ -188,16 +189,18 @@ mt76_dma_queue_magic_cnt_init(struct mt76_dev *dev, struct mt76_queue *q) · 176 unmodified lines
188static void189static void
189mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)190mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
190{191{
191 Q_WRITE(q, desc_base, q->desc_dma);192 if ((q->flags & MT_QFLAG_WED_RRO_EN) &&
192 if ((q->flags & MT_QFLAG_WED_RRO_EN) && !mt76_npu_device_active(dev))193 (!is_mt7992(dev) || !mt76_npu_device_active(dev)))
193 Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc);194 Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc);
194 else195 else
195 Q_WRITE(q, ring_size, q->ndesc);196 Q_WRITE(q, ring_size, q->ndesc);
196 197
197 if (mt76_queue_is_npu_tx(q)) {198 if (mt76_queue_is_npu_tx(q)) {
198 writel(q->desc_dma, &q->regs->desc_base);
199 writel(q->ndesc, &q->regs->ring_size);199 writel(q->ndesc, &q->regs->ring_size);
200 writel(q->desc_dma, &q->regs->desc_base);
200 }201 }
202
203 Q_WRITE(q, desc_base, q->desc_dma);
201 q->head = Q_READ(q, dma_idx);204 q->head = Q_READ(q, dma_idx);
202 q->tail = q->head;205 q->tail = q->head;
203}206}
@@ -663,6 +666,8 @@ mt76_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q, · 459 unmodified lines
663 if (!t)666 if (!t)
664 goto free_skb;667 goto free_skb;
665 668
669 t->phy_idx = phy->band_idx;
670 t->qid = qid;
666 txwi = mt76_get_txwi_ptr(dev, t);671 txwi = mt76_get_txwi_ptr(dev, t);
667 672
668 skb->prev = skb->next = NULL;673 skb->prev = skb->next = NULL;
@@ -874,7 +879,16 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) · 205 unmodified lines
874 if (!buf)879 if (!buf)
875 break;880 break;
876 881
877 if (!mt76_queue_is_wed_rro(q))882 if (mtk_wed_device_active(&dev->mmio.wed) &&
883 mt76_queue_is_wed_rro(q))
884 continue;
885
886 if (mt76_npu_device_active(dev) &&
887 mt76_queue_is_wed_rro(q))
888 continue;
889
890 if (!mt76_queue_is_wed_rro_rxdmad_c(q) &&
891 !mt76_queue_is_wed_rro_ind(q))
878 mt76_put_page_pool_buf(buf, false);892 mt76_put_page_pool_buf(buf, false);
879 } while (1);893 } while (1);
880 894
@@ -915,6 +929,13 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) · 34 unmodified lines
915 mt76_queue_is_wed_rro(q))929 mt76_queue_is_wed_rro(q))
916 return;930 return;
917 931
932 if (mt76_npu_device_active(dev) &&
933 mt76_queue_is_wed_rro(q))
934 return;
935
936 if (mt76_queue_is_npu_txfree(q))
937 return;
938
918 mt76_dma_sync_idx(dev, q);939 mt76_dma_sync_idx(dev, q);
919 if (mt76_queue_is_npu(q))940 if (mt76_queue_is_npu(q))
920 mt76_npu_fill_rx_queue(dev, q);941 mt76_npu_fill_rx_queue(dev, q);
@@ -1168,10 +1189,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev) · 247 unmodified lines
1168 mt76_for_each_q_rx(dev, i) {1189 mt76_for_each_q_rx(dev, i) {
1169 struct mt76_queue *q = &dev->q_rx[i];1190 struct mt76_queue *q = &dev->q_rx[i];
1170 1191
1171 if (mtk_wed_device_active(&dev->mmio.wed) &&
1172 mt76_queue_is_wed_rro(q))
1173 continue;
1174
1175 netif_napi_del(&dev->napi[i]);1192 netif_napi_del(&dev->napi[i]);
1176 mt76_dma_rx_cleanup(dev, q);1193 mt76_dma_rx_cleanup(dev, q);
1177 1194
drivers/net/wireless/mediatek/mt76/dma.h+3−1
@@ -174,7 +174,9 @@ void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, · 173 unmodified lines
174static inline void174static inline void
175mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)175mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
176{176{
177 dev->queue_ops->reset_q(dev, q, true);177 bool reset_idx = q && !mt76_queue_is_npu_tx(q);
178
179 dev->queue_ops->reset_q(dev, q, reset_idx);
178 if (mtk_wed_device_active(&dev->mmio.wed))180 if (mtk_wed_device_active(&dev->mmio.wed))
179 mt76_wed_dma_setup(dev, q, true);181 mt76_wed_dma_setup(dev, q, true);
180}182}
drivers/net/wireless/mediatek/mt76/eeprom.c+109−45
@@ -9,6 +9,13 @@ · 8 unmodified lines
9#include <linux/nvmem-consumer.h>9#include <linux/nvmem-consumer.h>
10#include <linux/etherdevice.h>10#include <linux/etherdevice.h>
11#include "mt76.h"11#include "mt76.h"
12#include "mt76_connac.h"
13
14enum mt76_sku_type {
15 MT76_SKU_RATE,
16 MT76_SKU_BACKOFF,
17 MT76_SKU_BACKOFF_BF_OFFSET,
18};
12 19
13static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)20static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)
14{21{
@@ -292,7 +299,6 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) · 277 unmodified lines
292}299}
293EXPORT_SYMBOL_GPL(mt76_find_channel_node);300EXPORT_SYMBOL_GPL(mt76_find_channel_node);
294 301
295
296static s8302static s8
297mt76_get_txs_delta(struct device_node *np, u8 nss)303mt76_get_txs_delta(struct device_node *np, u8 nss)
298{304{
@@ -306,9 +312,24 @@ mt76_get_txs_delta(struct device_node *np, u8 nss) · 7 unmodified lines
306 return be32_to_cpu(val[nss - 1]);312 return be32_to_cpu(val[nss - 1]);
307}313}
308 314
315static inline u8 mt76_backoff_n_chains(struct mt76_dev *dev, u8 idx)
316{
317 /* 0:1T1ss, 1:2T1ss, ..., 14:5T5ss */
318 static const u8 connac3_table[] = {
319 1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};
320 static const u8 connac2_table[] = {
321 1, 2, 3, 4, 2, 3, 4, 3, 4, 4, 0, 0, 0, 0, 0};
322
323 if (idx >= ARRAY_SIZE(connac3_table))
324 return 0;
325
326 return is_mt799x(dev) ? connac3_table[idx] : connac2_table[idx];
327}
328
309static void329static void
310mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,330mt76_apply_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
311 s8 target_power, s8 nss_delta, s8 *max_power)331 const s8 *data, s8 target_power, s8 nss_delta,
332 s8 *max_power, int n_chains, enum mt76_sku_type type)
312{333{
313 int i;334 int i;
314 335
@@ -316,18 +337,51 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data, · 1 unmodified line
316 return;337 return;
317 338
318 for (i = 0; i < pwr_len; i++) {339 for (i = 0; i < pwr_len; i++) {
319 pwr[i] = min_t(s8, target_power, data[i] + nss_delta);340 u8 backoff_chain_idx = i;
341 int backoff_n_chains;
342 s8 backoff_delta;
343 s8 delta;
344
345 switch (type) {
346 case MT76_SKU_RATE:
347 delta = 0;
348 backoff_delta = 0;
349 backoff_n_chains = 0;
350 break;
351 case MT76_SKU_BACKOFF_BF_OFFSET:
352 backoff_chain_idx += 1;
353 fallthrough;
354 case MT76_SKU_BACKOFF:
355 delta = mt76_tx_power_path_delta(n_chains);
356 backoff_n_chains = mt76_backoff_n_chains(dev, backoff_chain_idx);
357 backoff_delta = mt76_tx_power_path_delta(backoff_n_chains);
358 break;
359 default:
360 return;
361 }
362
363 pwr[i] = min_t(s8, target_power + delta - backoff_delta, data[i] + nss_delta);
364
365 /* used for padding, doesn't need to be considered */
366 if (data[i] >= S8_MAX - 1)
367 continue;
368
369 /* only consider backoff value for the configured chain number */
370 if (type != MT76_SKU_RATE && n_chains != backoff_n_chains)
371 continue;
372
320 *max_power = max(*max_power, pwr[i]);373 *max_power = max(*max_power, pwr[i]);
321 }374 }
322}375}
323 376
324static void377static void
325mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,378mt76_apply_multi_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
326 const s8 *data, size_t len, s8 target_power,379 s8 pwr_num, const s8 *data, size_t len,
327 s8 nss_delta)380 s8 target_power, s8 nss_delta, s8 *max_power,
381 int n_chains, enum mt76_sku_type type)
328{382{
383 static const int connac2_backoff_ru_idx = 2;
329 int i, cur;384 int i, cur;
330 s8 max_power = -128;
331 385
332 if (!data)386 if (!data)
333 return;387 return;
@@ -337,8 +391,26 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, · 3 unmodified lines
337 if (len < pwr_len + 1)391 if (len < pwr_len + 1)
338 break;392 break;
339 393
340 mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1,394 /* Each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS
341 target_power, nss_delta, &max_power);395 * corresponds to 10 stream combinations (1T1ss, 2T1ss, 3T1ss,
396 * 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 4T3ss, 4T4ss).
397 *
398 * For beamforming tables:
399 * - In connac2, beamforming entries for BW20~BW160 and OFDM
400 * do not include 1T1ss.
401 * - In connac3, beamforming entries for BW20~BW160 and RU
402 * include 1T1ss, but OFDM beamforming does not include 1T1ss.
403 *
404 * Non-beamforming and RU entries for both connac2 and connac3
405 * include 1T1ss.
406 */
407 if (!is_mt799x(dev) && type == MT76_SKU_BACKOFF &&
408 i > connac2_backoff_ru_idx)
409 type = MT76_SKU_BACKOFF_BF_OFFSET;
410
411 mt76_apply_array_limit(dev, pwr + pwr_len * i, pwr_len, data + 1,
412 target_power, nss_delta, max_power,
413 n_chains, type);
342 if (--cur > 0)414 if (--cur > 0)
343 continue;415 continue;
344 416
@@ -360,18 +432,11 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, · 15 unmodified lines
360 struct device_node *np;432 struct device_node *np;
361 const s8 *val;433 const s8 *val;
362 char name[16];434 char name[16];
363 u32 mcs_rates = dev->drv->mcs_rates;
364 u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
365 char band;435 char band;
366 size_t len;436 size_t len;
367 s8 max_power = 0;437 s8 max_power = -127;
368 s8 max_power_backoff = -127;
369 s8 txs_delta;438 s8 txs_delta;
370 int n_chains = hweight16(phy->chainmask);439 int n_chains = hweight16(phy->chainmask);
371 s8 target_power_combine = target_power + mt76_tx_power_path_delta(n_chains);
372
373 if (!mcs_rates)
374 mcs_rates = 10;
375 440
376 memset(dest, target_power, sizeof(*dest) - sizeof(dest->path));441 memset(dest, target_power, sizeof(*dest) - sizeof(dest->path));
377 memset(&dest->path, 0, sizeof(dest->path));442 memset(&dest->path, 0, sizeof(dest->path));
@@ -409,46 +474,45 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, · 31 unmodified lines
409 txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));474 txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));
410 475
411 val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));476 val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
412 mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,477 mt76_apply_array_limit(dev, dest->cck, ARRAY_SIZE(dest->cck), val,
413 target_power, txs_delta, &max_power);478 target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
414 479
415 val = mt76_get_of_array_s8(np, "rates-ofdm",480 val = mt76_get_of_array_s8(np, "rates-ofdm", &len, ARRAY_SIZE(dest->ofdm));
416 &len, ARRAY_SIZE(dest->ofdm));481 mt76_apply_array_limit(dev, dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
417 mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val,482 target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
418 target_power, txs_delta, &max_power);
419 483
420 val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1);484 val = mt76_get_of_array_s8(np, "rates-mcs", &len, ARRAY_SIZE(dest->mcs[0]) + 1);
421 mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),485 mt76_apply_multi_array_limit(dev, dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
422 ARRAY_SIZE(dest->mcs), val, len,486 ARRAY_SIZE(dest->mcs), val, len, target_power,
423 target_power, txs_delta);487 txs_delta, &max_power, n_chains, MT76_SKU_RATE);
424 488
425 val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1);489 val = mt76_get_of_array_s8(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
426 mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),490 mt76_apply_multi_array_limit(dev, dest->ru[0], ARRAY_SIZE(dest->ru[0]),
427 ARRAY_SIZE(dest->ru), val, len,491 ARRAY_SIZE(dest->ru), val, len, target_power,
428 target_power, txs_delta);492 txs_delta, &max_power, n_chains, MT76_SKU_RATE);
429 493
430 max_power_backoff = max_power;
431 val = mt76_get_of_array_s8(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck));494 val = mt76_get_of_array_s8(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck));
432 mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val,495 mt76_apply_array_limit(dev, dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
433 target_power_combine, txs_delta, &max_power_backoff);496 target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
434 497
435 val = mt76_get_of_array_s8(np, "paths-ofdm", &len, ARRAY_SIZE(dest->path.ofdm));498 val = mt76_get_of_array_s8(np, "paths-ofdm", &len, ARRAY_SIZE(dest->path.ofdm));
436 mt76_apply_array_limit(dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,499 mt76_apply_array_limit(dev, dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
437 target_power_combine, txs_delta, &max_power_backoff);500 target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
438 501
439 val = mt76_get_of_array_s8(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->path.ofdm_bf));502 val = mt76_get_of_array_s8(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->path.ofdm_bf));
440 mt76_apply_array_limit(dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,503 mt76_apply_array_limit(dev, dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
441 target_power_combine, txs_delta, &max_power_backoff);504 target_power, txs_delta, &max_power, n_chains,
505 MT76_SKU_BACKOFF_BF_OFFSET);
442 506
443 val = mt76_get_of_array_s8(np, "paths-ru", &len, ARRAY_SIZE(dest->path.ru[0]) + 1);507 val = mt76_get_of_array_s8(np, "paths-ru", &len, ARRAY_SIZE(dest->path.ru[0]) + 1);
444 mt76_apply_multi_array_limit(dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),508 mt76_apply_multi_array_limit(dev, dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
445 ARRAY_SIZE(dest->path.ru), val, len,509 ARRAY_SIZE(dest->path.ru), val, len, target_power,
446 target_power_combine, txs_delta);510 txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
447 511
448 val = mt76_get_of_array_s8(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->path.ru_bf[0]) + 1);512 val = mt76_get_of_array_s8(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->path.ru_bf[0]) + 1);
449 mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),513 mt76_apply_multi_array_limit(dev, dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
450 ARRAY_SIZE(dest->path.ru_bf), val, len,514 ARRAY_SIZE(dest->path.ru_bf), val, len, target_power,
451 target_power_combine, txs_delta);515 txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
452 516
453 return max_power;517 return max_power;
454}518}
drivers/net/wireless/mediatek/mt76/mac80211.c+228−2
@@ -726,6 +726,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size, · 725 unmodified lines
726 INIT_LIST_HEAD(&dev->rxwi_cache);726 INIT_LIST_HEAD(&dev->rxwi_cache);
727 dev->token_size = dev->drv->token_size;727 dev->token_size = dev->drv->token_size;
728 INIT_DELAYED_WORK(&dev->scan_work, mt76_scan_work);728 INIT_DELAYED_WORK(&dev->scan_work, mt76_scan_work);
729 spin_lock_init(&dev->scan_lock);
729 730
730 for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)731 for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
731 skb_queue_head_init(&dev->rx_skb[i]);732 skb_queue_head_init(&dev->rx_skb[i]);
@@ -970,6 +971,9 @@ bool mt76_has_tx_pending(struct mt76_phy *phy) · 238 unmodified lines
970 return true;971 return true;
971 }972 }
972 973
974 if (atomic_read(&phy->mgmt_tx_pending))
975 return true;
976
973 return false;977 return false;
974}978}
975EXPORT_SYMBOL_GPL(mt76_has_tx_pending);979EXPORT_SYMBOL_GPL(mt76_has_tx_pending);
@@ -1030,9 +1034,10 @@ int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef, · 54 unmodified lines
1030 int timeout = HZ / 5;1034 int timeout = HZ / 5;
1031 int ret;1035 int ret;
1032 1036
1033 set_bit(MT76_RESET, &phy->state);
1034
1035 mt76_worker_disable(&dev->tx_worker);1037 mt76_worker_disable(&dev->tx_worker);
1038 mt76_txq_schedule_pending(phy);
1039
1040 set_bit(MT76_RESET, &phy->state);
1036 wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout);1041 wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout);
1037 mt76_update_survey(phy);1042 mt76_update_survey(phy);
1038 1043
@@ -1716,6 +1721,16 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid) · 677 unmodified lines
1716 1721
1717 idr_destroy(&wcid->pktid);1722 idr_destroy(&wcid->pktid);
1718 1723
1724 /* Remove from sta_poll_list to prevent list corruption after reset.
1725 * Without this, mt76_reset_device() reinitializes sta_poll_list but
1726 * leaves wcid->poll_list with stale pointers, causing list corruption
1727 * when mt76_wcid_add_poll() checks list_empty().
1728 */
1729 spin_lock_bh(&dev->sta_poll_lock);
1730 if (!list_empty(&wcid->poll_list))
1731 list_del_init(&wcid->poll_list);
1732 spin_unlock_bh(&dev->sta_poll_lock);
1733
1719 spin_lock_bh(&phy->tx_lock);1734 spin_lock_bh(&phy->tx_lock);
1720 1735
1721 if (!list_empty(&wcid->tx_list))1736 if (!list_empty(&wcid->tx_list))
@@ -2121,3 +2136,214 @@ u16 mt76_select_links(struct ieee80211_vif *vif, int max_active_links) · 399 unmodified lines
2121 return sel_links;2136 return sel_links;
2122}2137}
2123EXPORT_SYMBOL_GPL(mt76_select_links);2138EXPORT_SYMBOL_GPL(mt76_select_links);
2139
2140struct mt76_offchannel_cb_data {
2141 struct mt76_phy *phy;
2142 bool offchannel;
2143};
2144
2145static void
2146mt76_offchannel_send_nullfunc(struct mt76_offchannel_cb_data *data,
2147 struct ieee80211_vif *vif, int link_id)
2148{
2149 struct mt76_phy *phy = data->phy;
2150 struct ieee80211_tx_info *info;
2151 struct ieee80211_sta *sta = NULL;
2152 struct ieee80211_hdr *hdr;
2153 struct mt76_wcid *wcid;
2154 struct sk_buff *skb;
2155
2156 skb = ieee80211_nullfunc_get(phy->hw, vif, link_id, true);
2157 if (!skb)
2158 return;
2159
2160 hdr = (struct ieee80211_hdr *)skb->data;
2161 if (data->offchannel)
2162 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
2163
2164 skb->priority = 7;
2165 skb_set_queue_mapping(skb, IEEE80211_AC_VO);
2166
2167 if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb,
2168 phy->main_chandef.chan->band,
2169 &sta))
2170 return;
2171
2172 if (sta)
2173 wcid = (struct mt76_wcid *)sta->drv_priv;
2174 else
2175 wcid = ((struct mt76_vif_link *)vif->drv_priv)->wcid;
2176
2177 if (link_id >= 0) {
2178 info = IEEE80211_SKB_CB(skb);
2179 info->control.flags &= ~IEEE80211_TX_CTRL_MLO_LINK;
2180 info->control.flags |=
2181 u32_encode_bits(link_id, IEEE80211_TX_CTRL_MLO_LINK);
2182 }
2183
2184 mt76_tx(phy, sta, wcid, skb);
2185}
2186
2187static void
2188mt76_offchannel_notify_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
2189{
2190 struct mt76_offchannel_cb_data *data = _data;
2191 struct mt76_vif_link *mlink;
2192 struct mt76_vif_data *mvif;
2193 int link_id;
2194
2195 if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
2196 return;
2197
2198 mlink = (struct mt76_vif_link *)vif->drv_priv;
2199 mvif = mlink->mvif;
2200
2201 if (!ieee80211_vif_is_mld(vif)) {
2202 if (mt76_vif_link_phy(mlink) == data->phy) {
2203 if (!data->offchannel && mlink->beacon_mon_interval)
2204 WRITE_ONCE(mlink->beacon_mon_last, jiffies);
2205 mt76_offchannel_send_nullfunc(data, vif, -1);
2206 }
2207 return;
2208 }
2209
2210 for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
2211 if (link_id == mvif->deflink_id)
2212 mlink = (struct mt76_vif_link *)vif->drv_priv;
2213 else
2214 mlink = rcu_dereference(mvif->link[link_id]);
2215 if (!mlink)
2216 continue;
2217 if (mt76_vif_link_phy(mlink) != data->phy)
2218 continue;
2219
2220 if (!data->offchannel && mlink->beacon_mon_interval)
2221 WRITE_ONCE(mlink->beacon_mon_last, jiffies);
2222
2223 mt76_offchannel_send_nullfunc(data, vif, link_id);
2224 }
2225}
2226
2227void mt76_offchannel_notify(struct mt76_phy *phy, bool offchannel)
2228{
2229 struct mt76_offchannel_cb_data data = {
2230 .phy = phy,
2231 .offchannel = offchannel,
2232 };
2233
2234 if (!phy->num_sta)
2235 return;
2236
2237 local_bh_disable();
2238 ieee80211_iterate_active_interfaces_atomic(phy->hw,
2239 IEEE80211_IFACE_ITER_NORMAL,
2240 mt76_offchannel_notify_iter, &data);
2241 local_bh_enable();
2242}
2243EXPORT_SYMBOL_GPL(mt76_offchannel_notify);
2244
2245struct mt76_rx_beacon_data {
2246 struct mt76_phy *phy;
2247 const u8 *bssid;
2248};
2249
2250static void mt76_rx_beacon_iter(void *_data, u8 *mac,
2251 struct ieee80211_vif *vif)
2252{
2253 struct mt76_rx_beacon_data *data = _data;
2254 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
2255 struct mt76_vif_data *mvif = mlink->mvif;
2256 int link_id;
2257
2258 if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
2259 return;
2260
2261 for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
2262 struct ieee80211_bss_conf *link_conf;
2263
2264 if (link_id == mvif->deflink_id)
2265 mlink = (struct mt76_vif_link *)vif->drv_priv;
2266 else
2267 mlink = rcu_dereference(mvif->link[link_id]);
2268 if (!mlink || !mlink->beacon_mon_interval)
2269 continue;
2270
2271 if (mt76_vif_link_phy(mlink) != data->phy)
2272 continue;
2273
2274 link_conf = rcu_dereference(vif->link_conf[link_id]);
2275 if (!link_conf)
2276 continue;
2277
2278 if (!ether_addr_equal(link_conf->bssid, data->bssid) &&
2279 (!link_conf->nontransmitted ||
2280 !ether_addr_equal(link_conf->transmitter_bssid,
2281 data->bssid)))
2282 continue;
2283
2284 WRITE_ONCE(mlink->beacon_mon_last, jiffies);
2285 }
2286}
2287
2288void mt76_rx_beacon(struct mt76_phy *phy, struct sk_buff *skb)
2289{
2290 struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
2291 struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
2292 struct mt76_rx_beacon_data data = {
2293 .phy = phy,
2294 .bssid = hdr->addr3,
2295 };
2296
2297 mt76_scan_rx_beacon(phy->dev, phy->chandef.chan);
2298
2299 if (!phy->num_sta)
2300 return;
2301
2302 if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_ONLY_MONITOR))
2303 return;
2304
2305 ieee80211_iterate_active_interfaces_atomic(phy->hw,
2306 IEEE80211_IFACE_ITER_RESUME_ALL,
2307 mt76_rx_beacon_iter, &data);
2308}
2309EXPORT_SYMBOL_GPL(mt76_rx_beacon);
2310
2311static void mt76_beacon_mon_iter(void *data, u8 *mac,
2312 struct ieee80211_vif *vif)
2313{
2314 struct mt76_phy *phy = data;
2315 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
2316 struct mt76_vif_data *mvif = mlink->mvif;
2317 int link_id;
2318
2319 if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
2320 return;
2321
2322 for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
2323 if (link_id == mvif->deflink_id)
2324 mlink = (struct mt76_vif_link *)vif->drv_priv;
2325 else
2326 mlink = rcu_dereference(mvif->link[link_id]);
2327 if (!mlink || !mlink->beacon_mon_interval)
2328 continue;
2329
2330 if (mt76_vif_link_phy(mlink) != phy)
2331 continue;
2332
2333 if (time_after(jiffies,
2334 READ_ONCE(mlink->beacon_mon_last) +
2335 MT76_BEACON_MON_MAX_MISS * mlink->beacon_mon_interval))
2336 ieee80211_beacon_loss(vif);
2337 }
2338}
2339
2340void mt76_beacon_mon_check(struct mt76_phy *phy)
2341{
2342 if (phy->offchannel)
2343 return;
2344
2345 ieee80211_iterate_active_interfaces_atomic(phy->hw,
2346 IEEE80211_IFACE_ITER_RESUME_ALL,
2347 mt76_beacon_mon_iter, phy);
2348}
2349EXPORT_SYMBOL_GPL(mt76_beacon_mon_check);
drivers/net/wireless/mediatek/mt76/mcu.c+1−1
@@ -98,7 +98,7 @@ retry: · 97 unmodified lines
98 /* orig skb might be needed for retry, mcu_skb_send_msg consumes it */98 /* orig skb might be needed for retry, mcu_skb_send_msg consumes it */
99 if (orig_skb)99 if (orig_skb)
100 skb_get(orig_skb);100 skb_get(orig_skb);
101 ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq);101 ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, wait_resp ? &seq : NULL);
102 if (ret < 0)102 if (ret < 0)
103 goto out;103 goto out;
104 104
drivers/net/wireless/mediatek/mt76/mt76.h+46−1
@@ -55,6 +55,8 @@ · 54 unmodified lines
55 FIELD_PREP(MT_QFLAG_WED_RING, _n))55 FIELD_PREP(MT_QFLAG_WED_RING, _n))
56#define MT_NPU_Q_TX(_n) __MT_NPU_Q(MT76_WED_Q_TX, _n)56#define MT_NPU_Q_TX(_n) __MT_NPU_Q(MT76_WED_Q_TX, _n)
57#define MT_NPU_Q_RX(_n) __MT_NPU_Q(MT76_WED_Q_RX, _n)57#define MT_NPU_Q_RX(_n) __MT_NPU_Q(MT76_WED_Q_RX, _n)
58#define MT_NPU_Q_TXFREE(_n) (FIELD_PREP(MT_QFLAG_WED_TYPE, MT76_WED_Q_TXFREE) | \
59 FIELD_PREP(MT_QFLAG_WED_RING, _n))
58 60
59struct mt76_dev;61struct mt76_dev;
60struct mt76_phy;62struct mt76_phy;
@@ -362,6 +364,7 @@ enum mt76_wcid_flags { · 301 unmodified lines
362};364};
363 365
364#define MT76_N_WCIDS 1088366#define MT76_N_WCIDS 1088
367#define MT76_BEACON_MON_MAX_MISS 7
365 368
366/* stored in ieee80211_tx_info::hw_queue */369/* stored in ieee80211_tx_info::hw_queue */
367#define MT_TX_HW_QUEUE_PHY GENMASK(3, 2)370#define MT_TX_HW_QUEUE_PHY GENMASK(3, 2)
@@ -448,6 +451,7 @@ struct mt76_txwi_cache { · 80 unmodified lines
448 };451 };
449 452
450 u8 qid;453 u8 qid;
454 u8 phy_idx;
451};455};
452 456
453struct mt76_rx_tid {457struct mt76_rx_tid {
@@ -540,7 +544,6 @@ struct mt76_driver_ops { · 86 unmodified lines
540 u32 survey_flags;544 u32 survey_flags;
541 u16 txwi_size;545 u16 txwi_size;
542 u16 token_size;546 u16 token_size;
543 u8 mcs_rates;
544 547
545 unsigned int link_data_size;548 unsigned int link_data_size;
546 549
@@ -831,6 +834,8 @@ struct mt76_vif_link { · 284 unmodified lines
831 u8 mcast_rates_idx;834 u8 mcast_rates_idx;
832 u8 beacon_rates_idx;835 u8 beacon_rates_idx;
833 bool offchannel;836 bool offchannel;
837 unsigned long beacon_mon_last;
838 u16 beacon_mon_interval;
834 struct ieee80211_chanctx_conf *ctx;839 struct ieee80211_chanctx_conf *ctx;
835 struct mt76_wcid *wcid;840 struct mt76_wcid *wcid;
836 struct mt76_vif_data *mvif;841 struct mt76_vif_data *mvif;
@@ -859,6 +864,8 @@ struct mt76_phy { · 22 unmodified lines
859 struct list_head tx_list;864 struct list_head tx_list;
860 struct mt76_queue *q_tx[__MT_TXQ_MAX];865 struct mt76_queue *q_tx[__MT_TXQ_MAX];
861 866
867 atomic_t mgmt_tx_pending;
868
862 struct cfg80211_chan_def chandef;869 struct cfg80211_chan_def chandef;
863 struct cfg80211_chan_def main_chandef;870 struct cfg80211_chan_def main_chandef;
864 bool offchannel;871 bool offchannel;
@@ -1002,6 +1009,7 @@ struct mt76_dev { · 137 unmodified lines
1002 u32 rxfilter;1009 u32 rxfilter;
1003 1010
1004 struct delayed_work scan_work;1011 struct delayed_work scan_work;
1012 spinlock_t scan_lock;
1005 struct {1013 struct {
1006 struct cfg80211_scan_request *req;1014 struct cfg80211_scan_request *req;
1007 struct ieee80211_channel *chan;1015 struct ieee80211_channel *chan;
@@ -1009,6 +1017,8 @@ struct mt76_dev { · 1 unmodified line
1009 struct mt76_vif_link *mlink;1017 struct mt76_vif_link *mlink;
1010 struct mt76_phy *phy;1018 struct mt76_phy *phy;
1011 int chan_idx;1019 int chan_idx;
1020 bool beacon_wait;
1021 bool beacon_received;
1012 } scan;1022 } scan;
1013 1023
1014#ifdef CONFIG_NL80211_TESTMODE1024#ifdef CONFIG_NL80211_TESTMODE
@@ -1518,6 +1528,7 @@ void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta, · 503 unmodified lines
1518void mt76_tx_check_agg_ssn(struct ieee80211_sta *sta, struct sk_buff *skb);1528void mt76_tx_check_agg_ssn(struct ieee80211_sta *sta, struct sk_buff *skb);
1519void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid);1529void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid);
1520void mt76_txq_schedule_all(struct mt76_phy *phy);1530void mt76_txq_schedule_all(struct mt76_phy *phy);
1531void mt76_txq_schedule_pending(struct mt76_phy *phy);
1521void mt76_tx_worker_run(struct mt76_dev *dev);1532void mt76_tx_worker_run(struct mt76_dev *dev);
1522void mt76_tx_worker(struct mt76_worker *w);1533void mt76_tx_worker(struct mt76_worker *w);
1523void mt76_release_buffered_frames(struct ieee80211_hw *hw,1534void mt76_release_buffered_frames(struct ieee80211_hw *hw,
@@ -1596,6 +1607,9 @@ int mt76_get_rate(struct mt76_dev *dev, · 72 unmodified lines
1596int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1607int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1597 struct ieee80211_scan_request *hw_req);1608 struct ieee80211_scan_request *hw_req);
1598void mt76_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif);1609void mt76_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
1610void mt76_scan_rx_beacon(struct mt76_dev *dev, struct ieee80211_channel *chan);
1611void mt76_rx_beacon(struct mt76_phy *phy, struct sk_buff *skb);
1612void mt76_beacon_mon_check(struct mt76_phy *phy);
1599void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1613void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1600 const u8 *mac);1614 const u8 *mac);
1601void mt76_sw_scan_complete(struct ieee80211_hw *hw,1615void mt76_sw_scan_complete(struct ieee80211_hw *hw,
@@ -1649,6 +1663,9 @@ void mt76_npu_txdesc_cleanup(struct mt76_queue *q, int index); · 47 unmodified lines
1649int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1663int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1650 struct net_device *dev, enum tc_setup_type type,1664 struct net_device *dev, enum tc_setup_type type,
1651 void *type_data);1665 void *type_data);
1666int mt76_npu_send_txrx_addr(struct mt76_dev *dev, int ifindex,
1667 u32 direction, u32 i_count_addr,
1668 u32 o_status_addr, u32 o_count_addr);
1652#else1669#else
1653static inline void mt76_npu_check_ppe(struct mt76_dev *dev,1670static inline void mt76_npu_check_ppe(struct mt76_dev *dev,
1654 struct sk_buff *skb, u32 info)1671 struct sk_buff *skb, u32 info)
@@ -1707,6 +1724,13 @@ static inline int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, · 52 unmodified lines
1707{1724{
1708 return -EOPNOTSUPP;1725 return -EOPNOTSUPP;
1709}1726}
1727
1728static inline int mt76_npu_send_txrx_addr(struct mt76_dev *dev, int ifindex,
1729 u32 direction, u32 i_count_addr,
1730 u32 o_status_addr, u32 o_count_addr)
1731{
1732 return -EOPNOTSUPP;
1733}
1710#endif /* CONFIG_MT76_NPU */1734#endif /* CONFIG_MT76_NPU */
1711 1735
1712static inline bool mt76_npu_device_active(struct mt76_dev *dev)1736static inline bool mt76_npu_device_active(struct mt76_dev *dev)
@@ -1775,6 +1799,18 @@ void mt76_queue_tx_complete(struct mt76_dev *dev, struct mt76_queue *q, · 62 unmodified lines
1775 struct mt76_queue_entry *e);1799 struct mt76_queue_entry *e);
1776int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,1800int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
1777 bool offchannel);1801 bool offchannel);
1802
1803static inline bool
1804mt76_offchannel_chandef(struct mt76_phy *phy, struct ieee80211_channel *chan,
1805 struct cfg80211_chan_def *chandef)
1806{
1807 cfg80211_chandef_create(chandef, chan, NL80211_CHAN_HT20);
1808 if (phy->main_chandef.chan != chan)
1809 return true;
1810
1811 *chandef = phy->main_chandef;
1812 return false;
1813}
1778int mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,1814int mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
1779 bool offchannel);1815 bool offchannel);
1780void mt76_scan_work(struct work_struct *work);1816void mt76_scan_work(struct work_struct *work);
@@ -1786,6 +1822,7 @@ struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy, · 5 unmodified lines
1786 struct ieee80211_vif *vif);1822 struct ieee80211_vif *vif);
1787void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,1823void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,
1788 struct mt76_vif_link *mlink);1824 struct mt76_vif_link *mlink);
1825void mt76_offchannel_notify(struct mt76_phy *phy, bool offchannel);
1789 1826
1790/* usb */1827/* usb */
1791static inline bool mt76u_urb_error(struct urb *urb)1828static inline bool mt76u_urb_error(struct urb *urb)
@@ -1993,6 +2030,14 @@ static inline bool mt76_queue_is_npu_rx(struct mt76_queue *q) · 201 unmodified lines
1993 FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;2030 FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
1994}2031}
1995 2032
2033static inline bool mt76_queue_is_npu_txfree(struct mt76_queue *q)
2034{
2035 if (q->flags & MT_QFLAG_WED)
2036 return false;
2037
2038 return FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
2039}
2040
1996struct mt76_txwi_cache *2041struct mt76_txwi_cache *
1997mt76_token_release(struct mt76_dev *dev, int token, bool *wake);2042mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
1998int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi);2043int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c+0−15
@@ -1167,21 +1167,6 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, · 1166 unmodified lines
1167}1167}
1168EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);1168EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);
1169 1169
1170void mt7615_mac_enable_rtscts(struct mt7615_dev *dev,
1171 struct ieee80211_vif *vif, bool enable)
1172{
1173 struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
1174 u32 addr;
1175
1176 addr = mt7615_mac_wtbl_addr(dev, mvif->sta.wcid.idx) + 3 * 4;
1177
1178 if (enable)
1179 mt76_set(dev, addr, MT_WTBL_W3_RTS);
1180 else
1181 mt76_clear(dev, addr, MT_WTBL_W3_RTS);
1182}
1183EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);
1184
1185static int1170static int
1186mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,1171mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
1187 struct ieee80211_key_conf *key,1172 struct ieee80211_key_conf *key,
drivers/net/wireless/mediatek/mt76/mt7615/main.c+4−3
@@ -583,9 +583,6 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, · 582 unmodified lines
583 }583 }
584 }584 }
585 585
586 if (changed & BSS_CHANGED_ERP_CTS_PROT)
587 mt7615_mac_enable_rtscts(dev, vif, info->use_cts_prot);
588
589 if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {586 if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
590 mt7615_mcu_add_bss_info(phy, vif, NULL, true);587 mt7615_mcu_add_bss_info(phy, vif, NULL, true);
591 mt7615_mcu_sta_add(phy, vif, NULL, true);588 mt7615_mcu_sta_add(phy, vif, NULL, true);
@@ -598,6 +595,10 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, · 6 unmodified lines
598 BSS_CHANGED_BEACON_ENABLED))595 BSS_CHANGED_BEACON_ENABLED))
599 mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon);596 mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon);
600 597
598 if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
599 mt7615_mcu_set_protection(phy, vif, info->ht_operation_mode,
600 info->use_cts_prot);
601
601 if (changed & BSS_CHANGED_PS)602 if (changed & BSS_CHANGED_PS)
602 mt76_connac_mcu_set_vif_ps(&dev->mt76, vif);603 mt76_connac_mcu_set_vif_ps(&dev->mt76, vif);
603 604
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c+47−0
@@ -2564,3 +2564,50 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, · 2563 unmodified lines
2564 return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_ROC),2564 return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_ROC),
2565 &req, sizeof(req), false);2565 &req, sizeof(req), false);
2566}2566}
2567
2568int mt7615_mcu_set_protection(struct mt7615_phy *phy, struct ieee80211_vif *vif,
2569 u8 ht_mode, bool use_cts_prot)
2570{
2571 struct mt7615_dev *dev = phy->dev;
2572 struct {
2573 u8 prot_idx;
2574 u8 band;
2575 u8 rsv[2];
2576
2577 bool long_nav;
2578 bool prot_mm;
2579 bool prot_gf;
2580 bool prot_bw40;
2581 bool prot_rifs;
2582 bool prot_bw80;
2583 bool prot_bw160;
2584 u8 prot_erp_mask;
2585 } __packed req = {
2586 .prot_idx = 0x2,
2587 .band = phy != &dev->phy,
2588 };
2589
2590 switch (ht_mode & IEEE80211_HT_OP_MODE_PROTECTION) {
2591 case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
2592 case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
2593 req.prot_mm = true;
2594 req.prot_gf = true;
2595 fallthrough;
2596 case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
2597 req.prot_bw40 = true;
2598 break;
2599 }
2600
2601 if (ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
2602 req.prot_gf = true;
2603
2604 if (use_cts_prot) {
2605 struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
2606 u8 i = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->mt76.omac_idx;
2607
2608 req.prot_erp_mask = BIT(i);
2609 }
2610
2611 return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(PROTECT_CTRL), &req,
2612 sizeof(req), true);
2613}
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h+2−3
@@ -467,8 +467,6 @@ void mt7615_mac_reset_counters(struct mt7615_phy *phy); · 466 unmodified lines
467void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy);467void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy);
468void mt7615_mac_set_scs(struct mt7615_phy *phy, bool enable);468void mt7615_mac_set_scs(struct mt7615_phy *phy, bool enable);
469void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy);469void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy);
470void mt7615_mac_enable_rtscts(struct mt7615_dev *dev,
471 struct ieee80211_vif *vif, bool enable);
472void mt7615_mac_sta_poll(struct mt7615_dev *dev);470void mt7615_mac_sta_poll(struct mt7615_dev *dev);
473int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,471int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
474 struct sk_buff *skb, struct mt76_wcid *wcid,472 struct sk_buff *skb, struct mt76_wcid *wcid,
@@ -523,7 +521,8 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable); · 48 unmodified lines
523int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);521int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);
524int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);522int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);
525int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);523int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);
526 524int mt7615_mcu_set_protection(struct mt7615_phy *phy, struct ieee80211_vif *vif,
525 u8 ht_mode, bool use_cts_prot);
527int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,526int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
528 struct ieee80211_channel *chan, int duration);527 struct ieee80211_channel *chan, int duration);
529 528
drivers/net/wireless/mediatek/mt76/mt7615/regs.h+0−2
@@ -455,8 +455,6 @@ enum mt7615_reg_base { · 454 unmodified lines
455#define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8)455#define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8)
456#define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20)456#define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20)
457 457
458#define MT_WTBL_W3_RTS BIT(22)
459
460#define MT_WTBL_W5_CHANGE_BW_RATE GENMASK(7, 5)458#define MT_WTBL_W5_CHANGE_BW_RATE GENMASK(7, 5)
461#define MT_WTBL_W5_SHORT_GI_20 BIT(8)459#define MT_WTBL_W5_SHORT_GI_20 BIT(8)
462#define MT_WTBL_W5_SHORT_GI_40 BIT(9)460#define MT_WTBL_W5_SHORT_GI_40 BIT(9)
drivers/net/wireless/mediatek/mt76/mt76_connac.h+9−2
@@ -182,14 +182,20 @@ static inline bool is_mt7920(struct mt76_dev *dev) · 181 unmodified lines
182 return mt76_chip(dev) == 0x7920;182 return mt76_chip(dev) == 0x7920;
183}183}
184 184
185static inline bool is_mt7902(struct mt76_dev *dev)
186{
187 return mt76_chip(dev) == 0x7902;
188}
189
185static inline bool is_mt7922(struct mt76_dev *dev)190static inline bool is_mt7922(struct mt76_dev *dev)
186{191{
187 return mt76_chip(dev) == 0x7922;192 return mt76_chip(dev) == 0x7922;
188}193}
189 194
190static inline bool is_mt7921(struct mt76_dev *dev)195static inline bool is_connac2(struct mt76_dev *dev)
191{196{
192 return mt76_chip(dev) == 0x7961 || is_mt7922(dev) || is_mt7920(dev);197 return mt76_chip(dev) == 0x7961 || is_mt7922(dev) || is_mt7920(dev) ||
198 is_mt7902(dev);
193}199}
194 200
195static inline bool is_mt7663(struct mt76_dev *dev)201static inline bool is_mt7663(struct mt76_dev *dev)
@@ -271,6 +277,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev) · 75 unmodified lines
271 case 0x7961:277 case 0x7961:
272 case 0x7920:278 case 0x7920:
273 case 0x7922:279 case 0x7922:
280 case 0x7902:
274 case 0x7925:281 case 0x7925:
275 case 0x7663:282 case 0x7663:
276 case 0x7622:283 case 0x7622:
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c+18−10
@@ -173,7 +173,7 @@ void mt76_connac_write_hw_txp(struct mt76_dev *dev, · 172 unmodified lines
173 173
174 txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);174 txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
175 175
176 if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))176 if (is_mt7663(dev) || is_connac2(dev) || is_mt7925(dev))
177 last_mask = MT_TXD_LEN_LAST;177 last_mask = MT_TXD_LEN_LAST;
178 else178 else
179 last_mask = MT_TXD_LEN_AMSDU_LAST |179 last_mask = MT_TXD_LEN_AMSDU_LAST |
@@ -217,7 +217,7 @@ mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev, · 37 unmodified lines
217 u32 last_mask;217 u32 last_mask;
218 int i;218 int i;
219 219
220 if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))220 if (is_mt7663(dev) || is_connac2(dev) || is_mt7925(dev))
221 last_mask = MT_TXD_LEN_LAST;221 last_mask = MT_TXD_LEN_LAST;
222 else222 else
223 last_mask = MT_TXD_LEN_MSDU_LAST;223 last_mask = MT_TXD_LEN_MSDU_LAST;
@@ -309,7 +309,7 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, · 85 unmodified lines
309 chandef = mvif->ctx ? &mvif->ctx->def : &mphy->chandef;309 chandef = mvif->ctx ? &mvif->ctx->def : &mphy->chandef;
310 band = chandef->chan->band;310 band = chandef->chan->band;
311 311
312 if (is_mt7921(mphy->dev)) {312 if (is_connac2(mphy->dev)) {
313 rateidx = ffs(conf->basic_rates) - 1;313 rateidx = ffs(conf->basic_rates) - 1;
314 goto legacy;314 goto legacy;
315 }315 }
@@ -548,7 +548,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, · 232 unmodified lines
548 val = MT_TXD1_LONG_FORMAT |548 val = MT_TXD1_LONG_FORMAT |
549 FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |549 FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
550 FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);550 FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
551 if (!is_mt7921(dev))551 if (!is_connac2(dev))
552 val |= MT_TXD1_VTA;552 val |= MT_TXD1_VTA;
553 if (phy_idx || band_idx)553 if (phy_idx || band_idx)
554 val |= MT_TXD1_TGID;554 val |= MT_TXD1_TGID;
@@ -557,7 +557,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, · 2 unmodified lines
557 txwi[2] = 0;557 txwi[2] = 0;
558 558
559 val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15);559 val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15);
560 if (!is_mt7921(dev))560 if (!is_connac2(dev))
561 val |= MT_TXD3_SW_POWER_MGMT;561 val |= MT_TXD3_SW_POWER_MGMT;
562 if (key)562 if (key)
563 val |= MT_TXD3_PROTECT_FRAME;563 val |= MT_TXD3_PROTECT_FRAME;
@@ -599,7 +599,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, · 35 unmodified lines
599 txwi[6] |= cpu_to_le32(val);599 txwi[6] |= cpu_to_le32(val);
600 txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);600 txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
601 601
602 if (!is_mt7921(dev)) {602 if (!is_connac2(dev)) {
603 u8 spe_idx = mt76_connac_spe_idx(mphy->antenna_mask);603 u8 spe_idx = mt76_connac_spe_idx(mphy->antenna_mask);
604 604
605 if (!spe_idx)605 if (!spe_idx)
@@ -831,7 +831,7 @@ mt76_connac2_mac_decode_he_mu_radiotap(struct mt76_dev *dev, struct sk_buff *skb · 225 unmodified lines
831 };831 };
832 struct ieee80211_radiotap_he_mu *he_mu;832 struct ieee80211_radiotap_he_mu *he_mu;
833 833
834 if (is_mt7921(dev)) {834 if (is_connac2(dev)) {
835 mu_known.flags1 |= HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN);835 mu_known.flags1 |= HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN);
836 mu_known.flags2 |= HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN);836 mu_known.flags2 |= HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN);
837 }837 }
@@ -1047,7 +1047,7 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, · 209 unmodified lines
1047 stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);1047 stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);
1048 gi = FIELD_GET(MT_PRXV_HT_SGI, v0);1048 gi = FIELD_GET(MT_PRXV_HT_SGI, v0);
1049 *mode = FIELD_GET(MT_PRXV_TX_MODE, v0);1049 *mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
1050 if (is_mt7921(dev))1050 if (is_connac2(dev))
1051 dcm = !!(idx & MT_PRXV_TX_DCM);1051 dcm = !!(idx & MT_PRXV_TX_DCM);
1052 else1052 else
1053 dcm = FIELD_GET(MT_PRXV_DCM, v0);1053 dcm = FIELD_GET(MT_PRXV_DCM, v0);
@@ -1153,8 +1153,10 @@ void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) · 99 unmodified lines
1153 return;1153 return;
1154 1154
1155 wcid = (struct mt76_wcid *)sta->drv_priv;1155 wcid = (struct mt76_wcid *)sta->drv_priv;
1156 if (!test_and_set_bit(tid, &wcid->ampdu_state))1156 if (!test_and_set_bit(tid, &wcid->ampdu_state)) {
1157 ieee80211_start_tx_ba_session(sta, tid, 0);1157 if (ieee80211_start_tx_ba_session(sta, tid, 0))
1158 clear_bit(tid, &wcid->ampdu_state);
1159 }
1158}1160}
1159EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr);1161EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr);
1160 1162
@@ -1207,5 +1209,11 @@ void mt76_connac2_tx_token_put(struct mt76_dev *dev) · 46 unmodified lines
1207 }1209 }
1208 spin_unlock_bh(&dev->token_lock);1210 spin_unlock_bh(&dev->token_lock);
1209 idr_destroy(&dev->token);1211 idr_destroy(&dev->token);
1212
1213 for (id = 0; id < __MT_MAX_BAND; id++) {
1214 struct mt76_phy *phy = dev->phys[id];
1215 if (phy)
1216 atomic_set(&phy->mgmt_tx_pending, 0);
1217 }
1210}1218}
1211EXPORT_SYMBOL_GPL(mt76_connac2_tx_token_put);1219EXPORT_SYMBOL_GPL(mt76_connac2_tx_token_put);
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c+29−17
@@ -4,6 +4,7 @@ · 3 unmodified lines
4#include <linux/firmware.h>4#include <linux/firmware.h>
5#include "mt76_connac2_mac.h"5#include "mt76_connac2_mac.h"
6#include "mt76_connac_mcu.h"6#include "mt76_connac_mcu.h"
7#include "mt792x_regs.h"
7 8
8int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)9int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
9{10{
@@ -65,7 +66,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len, · 55 unmodified lines
65 int cmd;66 int cmd;
66 67
67 if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||68 if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
68 (is_mt7921(dev) && addr == 0x900000) ||69 (is_connac2(dev) && addr == 0x900000) ||
69 (is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||70 (is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
70 (is_mt799x(dev) && addr == 0x900000))71 (is_mt799x(dev) && addr == 0x900000))
71 cmd = MCU_CMD(PATCH_START_REQ);72 cmd = MCU_CMD(PATCH_START_REQ);
@@ -402,7 +403,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, · 330 unmodified lines
402 switch (vif->type) {403 switch (vif->type) {
403 case NL80211_IFTYPE_MESH_POINT:404 case NL80211_IFTYPE_MESH_POINT:
404 case NL80211_IFTYPE_AP:405 case NL80211_IFTYPE_AP:
405 if (vif->p2p && !is_mt7921(dev))406 if (vif->p2p && !is_connac2(dev))
406 conn_type = CONNECTION_P2P_GC;407 conn_type = CONNECTION_P2P_GC;
407 else408 else
408 conn_type = CONNECTION_INFRA_STA;409 conn_type = CONNECTION_INFRA_STA;
@@ -410,7 +411,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, · 1 unmodified line
410 basic->aid = cpu_to_le16(link_sta->sta->aid);411 basic->aid = cpu_to_le16(link_sta->sta->aid);
411 break;412 break;
412 case NL80211_IFTYPE_STATION:413 case NL80211_IFTYPE_STATION:
413 if (vif->p2p && !is_mt7921(dev))414 if (vif->p2p && !is_connac2(dev))
414 conn_type = CONNECTION_P2P_GO;415 conn_type = CONNECTION_P2P_GO;
415 else416 else
416 conn_type = CONNECTION_INFRA_AP;417 conn_type = CONNECTION_INFRA_AP;
@@ -874,7 +875,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, · 457 unmodified lines
874 struct sta_rec_vht *vht;875 struct sta_rec_vht *vht;
875 int len;876 int len;
876 877
877 len = is_mt7921(dev) ? sizeof(*vht) : sizeof(*vht) - 4;878 len = is_connac2(dev) ? sizeof(*vht) : sizeof(*vht) - 4;
878 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, len);879 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, len);
879 vht = (struct sta_rec_vht *)tlv;880 vht = (struct sta_rec_vht *)tlv;
880 vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap);881 vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap);
@@ -885,7 +886,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, · 4 unmodified lines
885 /* starec uapsd */886 /* starec uapsd */
886 mt76_connac_mcu_sta_uapsd(skb, vif, sta);887 mt76_connac_mcu_sta_uapsd(skb, vif, sta);
887 888
888 if (!is_mt7921(dev))889 if (!is_connac2(dev))
889 return;890 return;
890 891
891 if (sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)892 if (sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)
@@ -1295,8 +1296,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, · 403 unmodified lines
1295 wtbl_hdr);1296 wtbl_hdr);
1296 1297
1297 ret = mt76_connac_mcu_sta_wed_update(dev, skb);1298 ret = mt76_connac_mcu_sta_wed_update(dev, skb);
1298 if (ret)1299 if (ret) {
1300 dev_kfree_skb(skb);
1299 return ret;1301 return ret;
1302 }
1300 1303
1301 ret = mt76_mcu_skb_send_msg(dev, skb, cmd, true);1304 ret = mt76_mcu_skb_send_msg(dev, skb, cmd, true);
1302 if (ret)1305 if (ret)
@@ -1309,8 +1312,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, · 6 unmodified lines
1309 mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);1312 mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);
1310 1313
1311 ret = mt76_connac_mcu_sta_wed_update(dev, skb);1314 ret = mt76_connac_mcu_sta_wed_update(dev, skb);
1312 if (ret)1315 if (ret) {
1316 dev_kfree_skb(skb);
1313 return ret;1317 return ret;
1318 }
1314 1319
1315 return mt76_mcu_skb_send_msg(dev, skb, cmd, true);1320 return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
1316}1321}
@@ -1774,7 +1779,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, · 457 unmodified lines
1774 req->ssid_type_ext = n_ssids ? BIT(0) : 0;1779 req->ssid_type_ext = n_ssids ? BIT(0) : 0;
1775 req->ssids_num = n_ssids;1780 req->ssids_num = n_ssids;
1776 1781
1777 duration = is_mt7921(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;1782 duration = is_connac2(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;
1778 /* increase channel time for passive scan */1783 /* increase channel time for passive scan */
1779 if (!sreq->n_ssids)1784 if (!sreq->n_ssids)
1780 duration *= 2;1785 duration *= 2;
@@ -1817,7 +1822,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, · 36 unmodified lines
1817 req->ies_len = cpu_to_le16(sreq->ie_len);1822 req->ies_len = cpu_to_le16(sreq->ie_len);
1818 }1823 }
1819 1824
1820 if (is_mt7921(phy->dev))1825 if (is_connac2(phy->dev))
1821 req->scan_func |= SCAN_FUNC_SPLIT_SCAN;1826 req->scan_func |= SCAN_FUNC_SPLIT_SCAN;
1822 1827
1823 memcpy(req->bssid, sreq->bssid, ETH_ALEN);1828 memcpy(req->bssid, sreq->bssid, ETH_ALEN);
@@ -1893,7 +1898,7 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy, · 69 unmodified lines
1893 get_random_mask_addr(addr, sreq->mac_addr,1898 get_random_mask_addr(addr, sreq->mac_addr,
1894 sreq->mac_addr_mask);1899 sreq->mac_addr_mask);
1895 }1900 }
1896 if (is_mt7921(phy->dev)) {1901 if (is_connac2(phy->dev)) {
1897 req->mt7921.bss_idx = mvif->idx;1902 req->mt7921.bss_idx = mvif->idx;
1898 req->mt7921.delay = cpu_to_le32(sreq->delay);1903 req->mt7921.delay = cpu_to_le32(sreq->delay);
1899 }1904 }
@@ -2033,7 +2038,7 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku, · 133 unmodified lines
2033 struct mt76_power_limits *limits,2038 struct mt76_power_limits *limits,
2034 enum nl80211_band band)2039 enum nl80211_band band)
2035{2040{
2036 int max_power = is_mt7921(dev) ? 127 : 63;2041 int max_power = is_connac2(dev) ? 127 : 63;
2037 int i, offset = sizeof(limits->cck);2042 int i, offset = sizeof(limits->cck);
2038 2043
2039 memset(sku, max_power, MT_SKU_POWER_LIMIT);2044 memset(sku, max_power, MT_SKU_POWER_LIMIT);
@@ -2061,7 +2066,7 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku, · 21 unmodified lines
2061 offset += 12;2066 offset += 12;
2062 }2067 }
2063 2068
2064 if (!is_mt7921(dev))2069 if (!is_connac2(dev))
2065 return;2070 return;
2066 2071
2067 /* he */2072 /* he */
@@ -2117,7 +2122,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, · 49 unmodified lines
2117 enum nl80211_band band)2122 enum nl80211_band band)
2118{2123{
2119 struct mt76_dev *dev = phy->dev;2124 struct mt76_dev *dev = phy->dev;
2120 int sku_len, batch_len = is_mt7921(dev) ? 8 : 16;2125 int sku_len, batch_len = is_connac2(dev) ? 8 : 16;
2121 static const u8 chan_list_2ghz[] = {2126 static const u8 chan_list_2ghz[] = {
2122 1, 2, 3, 4, 5, 6, 7,2127 1, 2, 3, 4, 5, 6, 7,
2123 8, 9, 10, 11, 12, 13, 142128 8, 9, 10, 11, 12, 13, 14
@@ -2158,7 +2163,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, · 34 unmodified lines
2158 if (!limits)2163 if (!limits)
2159 return -ENOMEM;2164 return -ENOMEM;
2160 2165
2161 sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;2166 sku_len = is_connac2(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
2162 tx_power = 2 * phy->hw->conf.power_level;2167 tx_power = 2 * phy->hw->conf.power_level;
2163 if (!tx_power)2168 if (!tx_power)
2164 tx_power = 127;2169 tx_power = 127;
@@ -2242,6 +2247,9 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, · 77 unmodified lines
2242 false);2247 false);
2243 if (err < 0)2248 if (err < 0)
2244 goto out;2249 goto out;
2250
2251 /* read a CR to avoid PSE buffer underflow */
2252 mt76_connac_mcu_reg_rr(dev, MT_PSE_BASE);
2245 }2253 }
2246 2254
2247out:2255out:
@@ -2764,12 +2772,16 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, · 516 unmodified lines
2764 return PTR_ERR(skb);2772 return PTR_ERR(skb);
2765 2773
2766 ret = mt76_connac_mcu_sta_key_tlv(sta_key_conf, skb, key, cmd);2774 ret = mt76_connac_mcu_sta_key_tlv(sta_key_conf, skb, key, cmd);
2767 if (ret)2775 if (ret) {
2776 dev_kfree_skb(skb);
2768 return ret;2777 return ret;
2778 }
2769 2779
2770 ret = mt76_connac_mcu_sta_wed_update(dev, skb);2780 ret = mt76_connac_mcu_sta_wed_update(dev, skb);
2771 if (ret)2781 if (ret) {
2782 dev_kfree_skb(skb);
2772 return ret;2783 return ret;
2784 }
2773 2785
2774 return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);2786 return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
2775}2787}
@@ -3072,7 +3084,7 @@ static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info) · 296 unmodified lines
3072{3084{
3073 u32 mode = DL_MODE_NEED_RSP;3085 u32 mode = DL_MODE_NEED_RSP;
3074 3086
3075 if ((!is_mt7921(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT)3087 if ((!is_connac2(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT)
3076 return mode;3088 return mode;
3077 3089
3078 switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {3090 switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h+14−1
@@ -628,6 +628,13 @@ struct sta_rec_tx_proc { · 627 unmodified lines
628 __le32 flag;628 __le32 flag;
629} __packed;629} __packed;
630 630
631struct sta_rec_eml_op {
632 __le16 tag;
633 __le16 len;
634 u8 link_bitmap;
635 u8 link_ant_num[3];
636} __packed;
637
631/* wtbl_rec */638/* wtbl_rec */
632 639
633struct wtbl_req_hdr {640struct wtbl_req_hdr {
@@ -796,6 +803,7 @@ struct wtbl_raw { · 162 unmodified lines
796 sizeof(struct sta_rec_he_6g_capa) + \803 sizeof(struct sta_rec_he_6g_capa) + \
797 sizeof(struct sta_rec_pn_info) + \804 sizeof(struct sta_rec_pn_info) + \
798 sizeof(struct sta_rec_tx_proc) + \805 sizeof(struct sta_rec_tx_proc) + \
806 sizeof(struct sta_rec_eml_op) + \
799 sizeof(struct tlv) + \807 sizeof(struct tlv) + \
800 MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)808 MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
801 809
@@ -832,6 +840,7 @@ enum { · 30 unmodified lines
832 STA_REC_PN_INFO = 0x26,840 STA_REC_PN_INFO = 0x26,
833 STA_REC_KEY_V3 = 0x27,841 STA_REC_KEY_V3 = 0x27,
834 STA_REC_HDRT = 0x28,842 STA_REC_HDRT = 0x28,
843 STA_REC_EML_OP = 0x29,
835 STA_REC_HDR_TRANS = 0x2B,844 STA_REC_HDR_TRANS = 0x2B,
836 STA_REC_MAX_NUM845 STA_REC_MAX_NUM
837};846};
@@ -1308,7 +1317,9 @@ enum { · 470 unmodified lines
1308 MCU_UNI_CMD_PER_STA_INFO = 0x6d,1317 MCU_UNI_CMD_PER_STA_INFO = 0x6d,
1309 MCU_UNI_CMD_ALL_STA_INFO = 0x6e,1318 MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
1310 MCU_UNI_CMD_ASSERT_DUMP = 0x6f,1319 MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
1320 MCU_UNI_CMD_EXT_EEPROM_CTRL = 0x74,
1311 MCU_UNI_CMD_RADIO_STATUS = 0x80,1321 MCU_UNI_CMD_RADIO_STATUS = 0x80,
1322 MCU_UNI_CMD_MLD = 0x82,
1312 MCU_UNI_CMD_SDO = 0x88,1323 MCU_UNI_CMD_SDO = 0x88,
1313};1324};
1314 1325
@@ -1363,6 +1374,7 @@ enum { · 48 unmodified lines
1363 UNI_BSS_INFO_BASIC = 0,1374 UNI_BSS_INFO_BASIC = 0,
1364 UNI_BSS_INFO_RA = 1,1375 UNI_BSS_INFO_RA = 1,
1365 UNI_BSS_INFO_RLM = 2,1376 UNI_BSS_INFO_RLM = 2,
1377 UNI_BSS_INFO_PROTECT_INFO = 3,
1366 UNI_BSS_INFO_BSS_COLOR = 4,1378 UNI_BSS_INFO_BSS_COLOR = 4,
1367 UNI_BSS_INFO_HE_BASIC = 5,1379 UNI_BSS_INFO_HE_BASIC = 5,
1368 UNI_BSS_INFO_11V_MBSSID = 6,1380 UNI_BSS_INFO_11V_MBSSID = 6,
@@ -1383,6 +1395,7 @@ enum { · 14 unmodified lines
1383 UNI_BSS_INFO_MLD = 26,1395 UNI_BSS_INFO_MLD = 26,
1384 UNI_BSS_INFO_PM_DISABLE = 27,1396 UNI_BSS_INFO_PM_DISABLE = 27,
1385 UNI_BSS_INFO_EHT = 30,1397 UNI_BSS_INFO_EHT = 30,
1398 UNI_BSS_INFO_MLD_LINK_OP = 36,
1386};1399};
1387 1400
1388enum {1401enum {
@@ -1865,7 +1878,7 @@ mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa) · 476 unmodified lines
1865 1878
1866 ret |= feature_set & FW_FEATURE_SET_ENCRYPT ?1879 ret |= feature_set & FW_FEATURE_SET_ENCRYPT ?
1867 DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV : 0;1880 DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV : 0;
1868 if (is_mt7921(dev) || is_mt7925(dev))1881 if (is_connac2(dev) || is_mt7925(dev))
1869 ret |= feature_set & FW_FEATURE_ENCRY_MODE ?1882 ret |= feature_set & FW_FEATURE_ENCRY_MODE ?
1870 DL_CONFIG_ENCRY_MODE_SEL : 0;1883 DL_CONFIG_ENCRY_MODE_SEL : 0;
1871 ret |= FIELD_PREP(DL_MODE_KEY_IDX,1884 ret |= FIELD_PREP(DL_MODE_KEY_IDX,
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c+1−0
@@ -534,6 +534,7 @@ void mt76x02_reconfig_complete(struct ieee80211_hw *hw, · 533 unmodified lines
534 return;534 return;
535 535
536 clear_bit(MT76_RESTART, &dev->mphy.state);536 clear_bit(MT76_RESTART, &dev->mphy.state);
537 ieee80211_wake_queues(hw);
537}538}
538EXPORT_SYMBOL_GPL(mt76x02_reconfig_complete);539EXPORT_SYMBOL_GPL(mt76x02_reconfig_complete);
539 540
drivers/net/wireless/mediatek/mt76/mt7915/init.c+1−0
@@ -1294,6 +1294,7 @@ free_phy2: · 1293 unmodified lines
1294 1294
1295void mt7915_unregister_device(struct mt7915_dev *dev)1295void mt7915_unregister_device(struct mt7915_dev *dev)
1296{1296{
1297 cancel_work_sync(&dev->dump_work);
1297 mt7915_unregister_ext_phy(dev);1298 mt7915_unregister_ext_phy(dev);
1298 mt7915_coredump_unregister(dev);1299 mt7915_coredump_unregister(dev);
1299 mt7915_unregister_thermal(&dev->phy);1300 mt7915_unregister_thermal(&dev->phy);
drivers/net/wireless/mediatek/mt76/mt7915/mac.c+0−13
@@ -232,19 +232,6 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) · 231 unmodified lines
232 rcu_read_unlock();232 rcu_read_unlock();
233}233}
234 234
235void mt7915_mac_enable_rtscts(struct mt7915_dev *dev,
236 struct ieee80211_vif *vif, bool enable)
237{
238 struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
239 u32 addr;
240
241 addr = mt7915_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5);
242 if (enable)
243 mt76_set(dev, addr, BIT(5));
244 else
245 mt76_clear(dev, addr, BIT(5));
246}
247
248static void235static void
249mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q,236mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q,
250 struct mt7915_sta *msta, struct sk_buff *skb,237 struct mt7915_sta *msta, struct sk_buff *skb,
drivers/net/wireless/mediatek/mt76/mt7915/main.c+6−3
@@ -68,7 +68,7 @@ int mt7915_run(struct ieee80211_hw *hw) · 67 unmodified lines
68 if (ret)68 if (ret)
69 goto out;69 goto out;
70 70
71 ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b,71 ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, MT7915_RTS_LEN_THRES,
72 phy->mt76->band_idx);72 phy->mt76->band_idx);
73 if (ret)73 if (ret)
74 goto out;74 goto out;
@@ -633,8 +633,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, · 558 unmodified lines
633 if (set_sta == 1)633 if (set_sta == 1)
634 mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);634 mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);
635 635
636 if (changed & BSS_CHANGED_ERP_CTS_PROT)636 if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
637 mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);637 mt7915_mcu_set_protection(phy, vif, info->ht_operation_mode,
638 info->use_cts_prot);
638 639
639 if (changed & BSS_CHANGED_ERP_SLOT) {640 if (changed & BSS_CHANGED_ERP_SLOT) {
640 int slottime = 9;641 int slottime = 9;
@@ -851,8 +852,10 @@ int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, · 210 unmodified lines
851 return mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_PORT_SECURE, false);852 return mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_PORT_SECURE, false);
852 853
853 case MT76_STA_EVENT_DISASSOC:854 case MT76_STA_EVENT_DISASSOC:
855 mutex_lock(&dev->mt76.mutex);
854 for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)856 for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
855 mt7915_mac_twt_teardown_flow(dev, msta, i);857 mt7915_mac_twt_teardown_flow(dev, msta, i);
858 mutex_unlock(&dev->mt76.mutex);
856 859
857 mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false);860 mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false);
858 msta->wcid.sta_disabled = 1;861 msta->wcid.sta_disabled = 1;
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c+65−1
@@ -1765,8 +1765,10 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, · 1764 unmodified lines
1765 }1765 }
1766out:1766out:
1767 ret = mt76_connac_mcu_sta_wed_update(&dev->mt76, skb);1767 ret = mt76_connac_mcu_sta_wed_update(&dev->mt76, skb);
1768 if (ret)1768 if (ret) {
1769 dev_kfree_skb(skb);
1769 return ret;1770 return ret;
1771 }
1770 1772
1771 return mt76_mcu_skb_send_msg(&dev->mt76, skb,1773 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
1772 MCU_EXT_CMD(STA_REC_UPDATE), true);1774 MCU_EXT_CMD(STA_REC_UPDATE), true);
@@ -3954,6 +3956,68 @@ out: · 2181 unmodified lines
3954 return ret;3956 return ret;
3955}3957}
3956 3958
3959int mt7915_mcu_set_protection(struct mt7915_phy *phy, struct ieee80211_vif *vif,
3960 u8 ht_mode, bool use_cts_prot)
3961{
3962 struct mt7915_dev *dev = phy->dev;
3963 int len = sizeof(struct sta_req_hdr) + sizeof(struct bss_info_prot);
3964 struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
3965 struct bss_info_prot *prot;
3966 struct sk_buff *skb;
3967 struct tlv *tlv;
3968 enum {
3969 PROT_NONMEMBER = BIT(1),
3970 PROT_20MHZ = BIT(2),
3971 PROT_NONHT_MIXED = BIT(3),
3972 PROT_LEGACY_ERP = BIT(5),
3973 PROT_NONGF_STA = BIT(7),
3974 };
3975 u32 rts_threshold;
3976
3977 skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
3978 NULL, len);
3979 if (IS_ERR(skb))
3980 return PTR_ERR(skb);
3981
3982 tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_PROTECT_INFO,
3983 sizeof(*prot));
3984 prot = (struct bss_info_prot *)tlv;
3985
3986 switch (ht_mode & IEEE80211_HT_OP_MODE_PROTECTION) {
3987 case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
3988 prot->prot_mode = cpu_to_le32(PROT_NONMEMBER);
3989 break;
3990 case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
3991 prot->prot_mode = cpu_to_le32(PROT_20MHZ);
3992 break;
3993 case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
3994 prot->prot_mode = cpu_to_le32(PROT_NONHT_MIXED);
3995 break;
3996 }
3997
3998 if (ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
3999 prot->prot_mode |= cpu_to_le32(PROT_NONGF_STA);
4000
4001 if (use_cts_prot)
4002 prot->prot_mode |= cpu_to_le32(PROT_LEGACY_ERP);
4003
4004 /* reuse current RTS setting */
4005 rts_threshold = phy->mt76->hw->wiphy->rts_threshold;
4006 if (rts_threshold == (u32)-1)
4007 prot->rts_len_thres = cpu_to_le32(MT7915_RTS_LEN_THRES);
4008 else
4009 prot->rts_len_thres = cpu_to_le32(rts_threshold);
4010
4011 prot->rts_pkt_thres = 0x2;
4012
4013 prot->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th);
4014 if (!prot->he_rts_thres)
4015 prot->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES);
4016
4017 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
4018 MCU_EXT_CMD(BSS_INFO_UPDATE), true);
4019}
4020
3957int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,4021int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
3958 struct cfg80211_he_bss_color *he_bss_color)4022 struct cfg80211_he_bss_color *he_bss_color)
3959{4023{
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h+11−0
@@ -399,6 +399,17 @@ struct bss_info_inband_discovery { · 398 unmodified lines
399 __le16 prob_rsp_len;399 __le16 prob_rsp_len;
400} __packed __aligned(4);400} __packed __aligned(4);
401 401
402struct bss_info_prot {
403 __le16 tag;
404 __le16 len;
405 __le32 prot_type;
406 __le32 prot_mode;
407 __le32 rts_len_thres;
408 __le16 he_rts_thres;
409 u8 rts_pkt_thres;
410 u8 rsv[5];
411} __packed;
412
402enum {413enum {
403 BSS_INFO_BCN_CSA,414 BSS_INFO_BCN_CSA,
404 BSS_INFO_BCN_BCC,415 BSS_INFO_BCN_BCC,
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h+4−0
@@ -84,6 +84,8 @@ · 83 unmodified lines
84#define MT7915_CRIT_TEMP 11084#define MT7915_CRIT_TEMP 110
85#define MT7915_MAX_TEMP 12085#define MT7915_MAX_TEMP 120
86 86
87#define MT7915_RTS_LEN_THRES 0x92b
88
87struct mt7915_vif;89struct mt7915_vif;
88struct mt7915_sta;90struct mt7915_sta;
89struct mt7915_dfs_pulse;91struct mt7915_dfs_pulse;
@@ -473,6 +475,8 @@ int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *v · 383 unmodified lines
473 u32 changed);475 u32 changed);
474int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,476int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
475 int enable, u32 changed);477 int enable, u32 changed);
478int mt7915_mcu_set_protection(struct mt7915_phy *phy, struct ieee80211_vif *vif,
479 u8 ht_mode, bool use_cts_prot);
476int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,480int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,
477 struct ieee80211_he_obss_pd *he_obss_pd);481 struct ieee80211_he_obss_pd *he_obss_pd);
478int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,482int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
drivers/net/wireless/mediatek/mt76/mt7921/init.c+3−1
@@ -302,7 +302,9 @@ int mt7921_register_device(struct mt792x_dev *dev) · 301 unmodified lines
302 dev->pm.idle_timeout = MT792x_PM_TIMEOUT;302 dev->pm.idle_timeout = MT792x_PM_TIMEOUT;
303 dev->pm.stats.last_wake_event = jiffies;303 dev->pm.stats.last_wake_event = jiffies;
304 dev->pm.stats.last_doze_event = jiffies;304 dev->pm.stats.last_doze_event = jiffies;
305 if (!mt76_is_usb(&dev->mt76)) {305
306 if (!mt76_is_usb(&dev->mt76) &&
307 !is_mt7902(&dev->mt76)) {
306 dev->pm.enable_user = true;308 dev->pm.enable_user = true;
307 dev->pm.enable = true;309 dev->pm.enable = true;
308 dev->pm.ds_enable_user = true;310 dev->pm.ds_enable_user = true;
drivers/net/wireless/mediatek/mt76/mt7921/main.c+20−9
@@ -371,12 +371,15 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev) · 370 unmodified lines
371{371{
372 struct mt792x_phy *phy = &dev->phy;372 struct mt792x_phy *phy = &dev->phy;
373 373
374 if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
375 return;
376
374 timer_delete_sync(&phy->roc_timer);377 timer_delete_sync(&phy->roc_timer);
375 cancel_work_sync(&phy->roc_work);378 cancel_work(&phy->roc_work);
376 if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))379
377 ieee80211_iterate_interfaces(mt76_hw(dev),380 ieee80211_iterate_interfaces(mt76_hw(dev),
378 IEEE80211_IFACE_ITER_RESUME_ALL,381 IEEE80211_IFACE_ITER_RESUME_ALL,
379 mt7921_roc_iter, (void *)phy);382 mt7921_roc_iter, (void *)phy);
380}383}
381EXPORT_SYMBOL_GPL(mt7921_roc_abort_sync);384EXPORT_SYMBOL_GPL(mt7921_roc_abort_sync);
382 385
@@ -387,10 +390,11 @@ void mt7921_roc_work(struct work_struct *work) · 4 unmodified lines
387 phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,390 phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,
388 roc_work);391 roc_work);
389 392
390 if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
391 return;
392
393 mt792x_mutex_acquire(phy->dev);393 mt792x_mutex_acquire(phy->dev);
394 if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) {
395 mt792x_mutex_release(phy->dev);
396 return;
397 }
394 ieee80211_iterate_active_interfaces(phy->mt76->hw,398 ieee80211_iterate_active_interfaces(phy->mt76->hw,
395 IEEE80211_IFACE_ITER_RESUME_ALL,399 IEEE80211_IFACE_ITER_RESUME_ALL,
396 mt7921_roc_iter, phy);400 mt7921_roc_iter, phy);
@@ -796,7 +800,8 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add) · 399 unmodified lines
796 }800 }
797 801
798out:802out:
799 mt7921_mcu_set_clc(dev, dev->mt76.alpha2, dev->country_ie_env);803 if (vif->bss_conf.chanreq.oper.chan->band == NL80211_BAND_6GHZ)
804 mt7921_regd_update(dev);
800}805}
801 806
802int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,807int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@@ -807,6 +812,9 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, · 4 unmodified lines
807 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;812 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
808 int ret, idx;813 int ret, idx;
809 814
815 if (sta->aid > MT7921_MAX_AID)
816 return -ENOENT;
817
810 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);818 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);
811 if (idx < 0)819 if (idx < 0)
812 return -ENOSPC;820 return -ENOSPC;
@@ -850,6 +858,9 @@ int mt7921_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, · 37 unmodified lines
850 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;858 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
851 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;859 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
852 860
861 if (sta->aid > MT7921_MAX_AID)
862 return -ENOENT;
863
853 if (ev != MT76_STA_EVENT_ASSOC)864 if (ev != MT76_STA_EVENT_ASSOC)
854 return 0;865 return 0;
855 866
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c+3−0
@@ -1353,6 +1353,9 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, · 1352 unmodified lines
1353 u16 len = le16_to_cpu(rule->len);1353 u16 len = le16_to_cpu(rule->len);
1354 u16 offset = len + sizeof(*rule);1354 u16 offset = len + sizeof(*rule);
1355 1355
1356 if (buf_len < offset)
1357 break;
1358
1356 pos += offset;1359 pos += offset;
1357 buf_len -= offset;1360 buf_len -= offset;
1358 if (rule->alpha2[0] != alpha2[0] ||1361 if (rule->alpha2[0] != alpha2[0] ||
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h+16−0
@@ -7,6 +7,8 @@ · 6 unmodified lines
7#include "../mt792x.h"7#include "../mt792x.h"
8#include "regs.h"8#include "regs.h"
9 9
10#define MT7921_MAX_AID 20
11
10#define MT7921_TX_RING_SIZE 204812#define MT7921_TX_RING_SIZE 2048
11#define MT7921_TX_MCU_RING_SIZE 25613#define MT7921_TX_MCU_RING_SIZE 256
12#define MT7921_TX_FWDL_RING_SIZE 12814#define MT7921_TX_FWDL_RING_SIZE 128
@@ -15,6 +17,9 @@ · 2 unmodified lines
15#define MT7921_RX_MCU_RING_SIZE 817#define MT7921_RX_MCU_RING_SIZE 8
16#define MT7921_RX_MCU_WA_RING_SIZE 51218#define MT7921_RX_MCU_WA_RING_SIZE 512
17 19
20/* MT7902 Rx Ring0 is for both Rx Event and Tx Done Event */
21#define MT7902_RX_MCU_RING_SIZE 512
22
18#define MT7921_EEPROM_SIZE 358423#define MT7921_EEPROM_SIZE 3584
19#define MT7921_TOKEN_SIZE 819224#define MT7921_TOKEN_SIZE 8192
20 25
@@ -117,6 +122,17 @@ enum mt7921_rxq_id { · 96 unmodified lines
117 MT7921_RXQ_MCU_WM = 0,122 MT7921_RXQ_MCU_WM = 0,
118};123};
119 124
125/* MT7902 assigns its MCU-WM TXQ at index 15 */
126enum mt7902_txq_id {
127 MT7902_TXQ_MCU_WM = 15,
128};
129
130struct mt7921_dma_layout {
131 u8 mcu_wm_txq;
132 u16 mcu_rxdone_ring_size;
133 bool has_mcu_wa;
134};
135
120enum {136enum {
121 MT7921_CLC_POWER,137 MT7921_CLC_POWER,
122 MT7921_CLC_CHAN,138 MT7921_CLC_CHAN,
drivers/net/wireless/mediatek/mt76/mt7921/pci.c+56−14
@@ -26,6 +26,8 @@ static const struct pci_device_id mt7921_pci_device_table[] = { · 25 unmodified lines
26 .driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },26 .driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
27 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7920),27 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7920),
28 .driver_data = (kernel_ulong_t)MT7920_FIRMWARE_WM },28 .driver_data = (kernel_ulong_t)MT7920_FIRMWARE_WM },
29 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7902),
30 .driver_data = (kernel_ulong_t)MT7902_FIRMWARE_WM },
29 { },31 { },
30};32};
31 33
@@ -167,8 +169,29 @@ static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) · 135 unmodified lines
167 169
168static int mt7921_dma_init(struct mt792x_dev *dev)170static int mt7921_dma_init(struct mt792x_dev *dev)
169{171{
172 struct mt7921_dma_layout layout = {
173 /* General case: MT7921 / MT7922 /MT7920 */
174 .mcu_wm_txq = MT7921_TXQ_MCU_WM,
175 .mcu_rxdone_ring_size = MT7921_RX_MCU_RING_SIZE,
176 .has_mcu_wa = true,
177 };
178 bool is_mt7902;
170 int ret;179 int ret;
171 180
181 is_mt7902 = mt7921_l1_rr(dev, MT_HW_CHIPID) == 0x7902;
182
183 /*
184 * MT7902 special case:
185 * - MCU-WM TXQ uses index 15
186 * - RX Ring0 is larger and shared for event/TX-done
187 * - MT7902 does not use the MCU_WA ring
188 */
189 if (is_mt7902) {
190 layout.mcu_wm_txq = MT7902_TXQ_MCU_WM;
191 layout.mcu_rxdone_ring_size = MT7902_RX_MCU_RING_SIZE;
192 layout.has_mcu_wa = false;
193 }
194
172 mt76_dma_attach(&dev->mt76);195 mt76_dma_attach(&dev->mt76);
173 196
174 ret = mt792x_dma_disable(dev, true);197 ret = mt792x_dma_disable(dev, true);
@@ -185,7 +208,7 @@ static int mt7921_dma_init(struct mt792x_dev *dev) · 10 unmodified lines
185 mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);208 mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
186 209
187 /* command to WM */210 /* command to WM */
188 ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM,211 ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, layout.mcu_wm_txq,
189 MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE);212 MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
190 if (ret)213 if (ret)
191 return ret;214 return ret;
@@ -199,18 +222,20 @@ static int mt7921_dma_init(struct mt792x_dev *dev) · 7 unmodified lines
199 /* event from WM before firmware download */222 /* event from WM before firmware download */
200 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],223 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
201 MT7921_RXQ_MCU_WM,224 MT7921_RXQ_MCU_WM,
202 MT7921_RX_MCU_RING_SIZE,225 layout.mcu_rxdone_ring_size,
203 MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);226 MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
204 if (ret)227 if (ret)
205 return ret;228 return ret;
206 229
207 /* Change mcu queue after firmware download */230 if (layout.has_mcu_wa) {
208 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],231 /* Change mcu queue after firmware download */
209 MT7921_RXQ_MCU_WM,232 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
210 MT7921_RX_MCU_WA_RING_SIZE,233 MT7921_RXQ_MCU_WM,
211 MT_RX_BUF_SIZE, MT_WFDMA0(0x540));234 MT7921_RX_MCU_WA_RING_SIZE,
212 if (ret)235 MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
213 return ret;236 if (ret)
237 return ret;
238 }
214 239
215 /* rx data */240 /* rx data */
216 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],241 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
@@ -276,6 +301,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, · 59 unmodified lines
276 struct mt76_bus_ops *bus_ops;301 struct mt76_bus_ops *bus_ops;
277 struct mt792x_dev *dev;302 struct mt792x_dev *dev;
278 struct mt76_dev *mdev;303 struct mt76_dev *mdev;
304 void __iomem *regs;
279 u16 cmd, chipid;305 u16 cmd, chipid;
280 u8 features;306 u8 features;
281 int ret;307 int ret;
@@ -284,10 +310,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev, · 2 unmodified lines
284 if (ret)310 if (ret)
285 return ret;311 return ret;
286 312
287 ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
288 if (ret)
289 return ret;
290
291 pci_read_config_word(pdev, PCI_COMMAND, &cmd);313 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
292 if (!(cmd & PCI_COMMAND_MEMORY)) {314 if (!(cmd & PCI_COMMAND_MEMORY)) {
293 cmd |= PCI_COMMAND_MEMORY;315 cmd |= PCI_COMMAND_MEMORY;
@@ -321,11 +343,29 @@ static int mt7921_pci_probe(struct pci_dev *pdev, · 27 unmodified lines
321 343
322 pci_set_drvdata(pdev, mdev);344 pci_set_drvdata(pdev, mdev);
323 345
346 regs = pcim_iomap_region(pdev, 0, pci_name(pdev));
347 if (IS_ERR(regs))
348 return PTR_ERR(regs);
349
324 dev = container_of(mdev, struct mt792x_dev, mt76);350 dev = container_of(mdev, struct mt792x_dev, mt76);
325 dev->fw_features = features;351 dev->fw_features = features;
326 dev->hif_ops = &mt7921_pcie_ops;352 dev->hif_ops = &mt7921_pcie_ops;
327 dev->irq_map = &irq_map;353 dev->irq_map = &irq_map;
328 mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);354 mt76_mmio_init(&dev->mt76, regs);
355
356 if (id->device == 0x7902) {
357 struct mt792x_irq_map *map;
358
359 /* MT7902 needs a mutable copy because wm2_complete_mask differs */
360 map = devm_kmemdup(&pdev->dev, &irq_map,
361 sizeof(irq_map), GFP_KERNEL);
362 if (!map)
363 return -ENOMEM;
364
365 map->rx.wm2_complete_mask = 0;
366 dev->irq_map = map;
367 }
368
329 tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);369 tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
330 370
331 dev->phy.dev = dev;371 dev->phy.dev = dev;
@@ -579,6 +619,8 @@ MODULE_FIRMWARE(MT7921_FIRMWARE_WM); · 247 unmodified lines
579MODULE_FIRMWARE(MT7921_ROM_PATCH);619MODULE_FIRMWARE(MT7921_ROM_PATCH);
580MODULE_FIRMWARE(MT7922_FIRMWARE_WM);620MODULE_FIRMWARE(MT7922_FIRMWARE_WM);
581MODULE_FIRMWARE(MT7922_ROM_PATCH);621MODULE_FIRMWARE(MT7922_ROM_PATCH);
622MODULE_FIRMWARE(MT7902_FIRMWARE_WM);
623MODULE_FIRMWARE(MT7902_ROM_PATCH);
582MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");624MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
583MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");625MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
584MODULE_DESCRIPTION("MediaTek MT7921E (PCIe) wireless driver");626MODULE_DESCRIPTION("MediaTek MT7921E (PCIe) wireless driver");
drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c+3−3
@@ -71,9 +71,9 @@ int mt7921e_mac_reset(struct mt792x_dev *dev) · 70 unmodified lines
71 mt76_txq_schedule_all(&dev->mphy);71 mt76_txq_schedule_all(&dev->mphy);
72 72
73 mt76_worker_disable(&dev->mt76.tx_worker);73 mt76_worker_disable(&dev->mt76.tx_worker);
74 napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]);74 mt76_for_each_q_rx(&dev->mt76, i) {
75 napi_disable(&dev->mt76.napi[MT_RXQ_MCU]);75 napi_disable(&dev->mt76.napi[i]);
76 napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);76 }
77 napi_disable(&dev->mt76.tx_napi);77 napi_disable(&dev->mt76.tx_napi);
78 78
79 mt76_connac2_tx_token_put(&dev->mt76);79 mt76_connac2_tx_token_put(&dev->mt76);
drivers/net/wireless/mediatek/mt76/mt7921/sdio.c+4−0
@@ -19,6 +19,8 @@ · 18 unmodified lines
19static const struct sdio_device_id mt7921s_table[] = {19static const struct sdio_device_id mt7921s_table[] = {
20 { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7901),20 { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7901),
21 .driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },21 .driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
22 { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7902),
23 .driver_data = (kernel_ulong_t)MT7902_FIRMWARE_WM },
22 { } /* Terminating entry */24 { } /* Terminating entry */
23};25};
24 26
@@ -317,6 +319,8 @@ failed: · 292 unmodified lines
317MODULE_DEVICE_TABLE(sdio, mt7921s_table);319MODULE_DEVICE_TABLE(sdio, mt7921s_table);
318MODULE_FIRMWARE(MT7921_FIRMWARE_WM);320MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
319MODULE_FIRMWARE(MT7921_ROM_PATCH);321MODULE_FIRMWARE(MT7921_ROM_PATCH);
322MODULE_FIRMWARE(MT7902_FIRMWARE_WM);
323MODULE_FIRMWARE(MT7902_ROM_PATCH);
320 324
321static DEFINE_SIMPLE_DEV_PM_OPS(mt7921s_pm_ops, mt7921s_suspend, mt7921s_resume);325static DEFINE_SIMPLE_DEV_PM_OPS(mt7921s_pm_ops, mt7921s_suspend, mt7921s_resume);
322 326
drivers/net/wireless/mediatek/mt76/mt7925/init.c+2−0
@@ -91,6 +91,8 @@ int mt7925_mac_init(struct mt792x_dev *dev) · 90 unmodified lines
91 91
92 mt7925_mac_init_basic_rates(dev);92 mt7925_mac_init_basic_rates(dev);
93 93
94 memzero_explicit(&dev->mt76.alpha2, sizeof(dev->mt76.alpha2));
95
94 return 0;96 return 0;
95}97}
96EXPORT_SYMBOL_GPL(mt7925_mac_init);98EXPORT_SYMBOL_GPL(mt7925_mac_init);
drivers/net/wireless/mediatek/mt76/mt7925/mac.c+12−6
@@ -804,8 +804,8 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, · 803 unmodified lines
804 txwi[5] = cpu_to_le32(val);804 txwi[5] = cpu_to_le32(val);
805 805
806 val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT, 1);806 val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
807 if (!ieee80211_vif_is_mld(vif) ||807 if (vif && (!ieee80211_vif_is_mld(vif) ||
808 (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0))808 (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)))
809 val |= MT_TXD6_DIS_MAT;809 val |= MT_TXD6_DIS_MAT;
810 txwi[6] = cpu_to_le32(val);810 txwi[6] = cpu_to_le32(val);
811 txwi[7] = 0;811 txwi[7] = 0;
@@ -846,11 +846,14 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb, · 34 unmodified lines
846 bool is_8023;846 bool is_8023;
847 u16 fc, tid;847 u16 fc, tid;
848 848
849 if (!sta)
850 return;
851
849 link_sta = rcu_dereference(sta->link[wcid->link_id]);852 link_sta = rcu_dereference(sta->link[wcid->link_id]);
850 if (!link_sta)853 if (!link_sta)
851 return;854 return;
852 855
853 if (!sta || !(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))856 if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
854 return;857 return;
855 858
856 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;859 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
@@ -882,8 +885,10 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb, · 25 unmodified lines
882 else885 else
883 mlink = &msta->deflink;886 mlink = &msta->deflink;
884 887
885 if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state))888 if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state)) {
886 ieee80211_start_tx_ba_session(sta, tid, 0);889 if (ieee80211_start_tx_ba_session(sta, tid, 0))
890 clear_bit(tid, &mlink->wcid.ampdu_state);
891 }
887}892}
888 893
889static bool894static bool
@@ -1280,7 +1285,8 @@ mt7925_vif_connect_iter(void *priv, u8 *mac, · 390 unmodified lines
1280 if (vif->type == NL80211_IFTYPE_AP) {1285 if (vif->type == NL80211_IFTYPE_AP) {
1281 mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.deflink.wcid,1286 mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.deflink.wcid,
1282 true, NULL);1287 true, NULL);
1283 mt7925_mcu_sta_update(dev, NULL, vif, true,1288 mt7925_mcu_sta_update(dev, NULL, vif,
1289 &mvif->sta.deflink, true,
1284 MT76_STA_INFO_STATE_NONE);1290 MT76_STA_INFO_STATE_NONE);
1285 mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true);1291 mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true);
1286 }1292 }
drivers/net/wireless/mediatek/mt76/mt7925/main.c+324−66
@@ -245,6 +245,7 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy) · 244 unmodified lines
245{245{
246 struct wiphy *wiphy = phy->mt76->hw->wiphy;246 struct wiphy *wiphy = phy->mt76->hw->wiphy;
247 static const u8 ext_capa_sta[] = {247 static const u8 ext_capa_sta[] = {
248 [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
248 [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,249 [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
249 [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,250 [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
250 };251 };
@@ -438,6 +439,9 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) · 187 unmodified lines
438 if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN)439 if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN)
439 vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI;440 vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI;
440 441
442 INIT_WORK(&mvif->csa_work, mt7925_csa_work);
443 timer_setup(&mvif->csa_timer, mt792x_csa_timer, 0);
444
441out:445out:
442 mt792x_mutex_release(dev);446 mt792x_mutex_release(dev);
443 447
@@ -457,12 +461,16 @@ void mt7925_roc_abort_sync(struct mt792x_dev *dev) · 13 unmodified lines
457{461{
458 struct mt792x_phy *phy = &dev->phy;462 struct mt792x_phy *phy = &dev->phy;
459 463
464 if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
465 return;
466
460 timer_delete_sync(&phy->roc_timer);467 timer_delete_sync(&phy->roc_timer);
461 cancel_work_sync(&phy->roc_work);468
462 if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))469 cancel_work(&phy->roc_work);
463 ieee80211_iterate_interfaces(mt76_hw(dev),470
464 IEEE80211_IFACE_ITER_RESUME_ALL,471 ieee80211_iterate_interfaces(mt76_hw(dev),
465 mt7925_roc_iter, (void *)phy);472 IEEE80211_IFACE_ITER_RESUME_ALL,
473 mt7925_roc_iter, (void *)phy);
466}474}
467EXPORT_SYMBOL_GPL(mt7925_roc_abort_sync);475EXPORT_SYMBOL_GPL(mt7925_roc_abort_sync);
468 476
@@ -541,7 +549,7 @@ static int mt7925_set_mlo_roc(struct mt792x_phy *phy, · 72 unmodified lines
541 549
542 phy->roc_grant = false;550 phy->roc_grant = false;
543 551
544 err = mt7925_mcu_set_mlo_roc(mconf, sel_links, 5, ++phy->roc_token_id);552 err = mt7925_mcu_set_mlo_roc(phy, mconf, sel_links, 5, ++phy->roc_token_id);
545 if (err < 0) {553 if (err < 0) {
546 clear_bit(MT76_STATE_ROC, &phy->mt76->state);554 clear_bit(MT76_STATE_ROC, &phy->mt76->state);
547 goto out;555 goto out;
@@ -586,7 +594,8 @@ static int mt7925_cancel_remain_on_channel(struct ieee80211_hw *hw, · 38 unmodified lines
586 594
587static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,595static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
588 struct ieee80211_vif *vif, struct ieee80211_sta *sta,596 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
589 struct ieee80211_key_conf *key, int link_id)597 struct ieee80211_key_conf *key, int link_id,
598 struct mt792x_link_sta *mlink)
590{599{
591 struct mt792x_dev *dev = mt792x_hw_dev(hw);600 struct mt792x_dev *dev = mt792x_hw_dev(hw);
592 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;601 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
@@ -595,7 +604,6 @@ static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, · 2 unmodified lines
595 struct ieee80211_bss_conf *link_conf;604 struct ieee80211_bss_conf *link_conf;
596 struct ieee80211_link_sta *link_sta;605 struct ieee80211_link_sta *link_sta;
597 int idx = key->keyidx, err = 0;606 int idx = key->keyidx, err = 0;
598 struct mt792x_link_sta *mlink;
599 struct mt792x_bss_conf *mconf;607 struct mt792x_bss_conf *mconf;
600 struct mt76_wcid *wcid;608 struct mt76_wcid *wcid;
601 u8 *wcid_keyidx;609 u8 *wcid_keyidx;
@@ -603,7 +611,6 @@ static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, · 1 unmodified line
603 link_conf = mt792x_vif_to_bss_conf(vif, link_id);611 link_conf = mt792x_vif_to_bss_conf(vif, link_id);
604 link_sta = sta ? mt792x_sta_to_link_sta(vif, sta, link_id) : NULL;612 link_sta = sta ? mt792x_sta_to_link_sta(vif, sta, link_id) : NULL;
605 mconf = mt792x_vif_to_link(mvif, link_id);613 mconf = mt792x_vif_to_link(mvif, link_id);
606 mlink = mt792x_sta_to_link(msta, link_id);
607 wcid = &mlink->wcid;614 wcid = &mlink->wcid;
608 wcid_keyidx = &wcid->hw_key_idx;615 wcid_keyidx = &wcid->hw_key_idx;
609 616
@@ -671,6 +678,7 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, · 61 unmodified lines
671 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;678 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
672 struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv :679 struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv :
673 &mvif->sta;680 &mvif->sta;
681 struct mt792x_link_sta *mlink;
674 int err;682 int err;
675 683
676 /* The hardware does not support per-STA RX GTK, fallback684 /* The hardware does not support per-STA RX GTK, fallback
@@ -692,12 +700,16 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, · 15 unmodified lines
692 add = key->link_id != -1 ? BIT(key->link_id) : msta->valid_links;700 add = key->link_id != -1 ? BIT(key->link_id) : msta->valid_links;
693 701
694 for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {702 for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
695 err = mt7925_set_link_key(hw, cmd, vif, sta, key, link_id);703 mlink = mt792x_sta_to_link(msta, link_id);
704 err = mt7925_set_link_key(hw, cmd, vif, sta, key, link_id,
705 mlink);
696 if (err < 0)706 if (err < 0)
697 break;707 break;
698 }708 }
699 } else {709 } else {
700 err = mt7925_set_link_key(hw, cmd, vif, sta, key, vif->bss_conf.link_id);710 mlink = mt792x_sta_to_link(msta, vif->bss_conf.link_id);
711 err = mt7925_set_link_key(hw, cmd, vif, sta, key,
712 vif->bss_conf.link_id, mlink);
701 }713 }
702 714
703 mt792x_mutex_release(dev);715 mt792x_mutex_release(dev);
@@ -842,20 +854,24 @@ mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 138 unmodified lines
842 854
843static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,855static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
844 struct ieee80211_vif *vif,856 struct ieee80211_vif *vif,
845 struct ieee80211_link_sta *link_sta)857 struct ieee80211_link_sta *link_sta,
858 struct mt792x_link_sta *mlink)
846{859{
847 struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);860 struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
848 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;861 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
849 struct ieee80211_bss_conf *link_conf;862 struct ieee80211_bss_conf *link_conf;
850 struct mt792x_bss_conf *mconf;863 struct mt792x_bss_conf *mconf;
851 u8 link_id = link_sta->link_id;864 u8 link_id = link_sta->link_id;
852 struct mt792x_link_sta *mlink;865 bool wcid_published = false;
853 struct mt792x_sta *msta;866 struct mt792x_sta *msta;
854 struct mt76_wcid *wcid;867 struct mt76_wcid *wcid;
868 bool pm_woken = false;
855 int ret, idx;869 int ret, idx;
856 870
857 msta = (struct mt792x_sta *)link_sta->sta->drv_priv;871 msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
858 mlink = mt792x_sta_to_link(msta, link_id);872
873 if (WARN_ON_ONCE(!mlink))
874 return -EINVAL;
859 875
860 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);876 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);
861 if (idx < 0)877 if (idx < 0)
@@ -874,14 +890,15 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, · 12 unmodified lines
874 wcid = &mlink->wcid;890 wcid = &mlink->wcid;
875 ewma_signal_init(&wcid->rssi);891 ewma_signal_init(&wcid->rssi);
876 rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid);892 rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid);
877 mt76_wcid_init(wcid, 0);893 wcid_published = true;
878 ewma_avg_signal_init(&mlink->avg_ack_signal);894 ewma_avg_signal_init(&mlink->avg_ack_signal);
879 memset(mlink->airtime_ac, 0,895 memset(mlink->airtime_ac, 0,
880 sizeof(msta->deflink.airtime_ac));896 sizeof(msta->deflink.airtime_ac));
881 897
882 ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm);898 ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
883 if (ret)899 if (ret)
884 return ret;900 goto out_wcid;
901 pm_woken = true;
885 902
886 mt7925_mac_wtbl_update(dev, idx,903 mt7925_mac_wtbl_update(dev, idx,
887 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);904 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -890,41 +907,125 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, · 2 unmodified lines
890 907
891 /* should update bss info before STA add */908 /* should update bss info before STA add */
892 if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) {909 if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) {
893 if (ieee80211_vif_is_mld(vif))910 struct mt792x_link_sta *mlink_bc;
894 mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,911
895 link_conf, link_sta, link_sta != mlink->pri_link);912 mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
896 else913
897 mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,914 if (ieee80211_vif_is_mld(vif)) {
898 link_conf, link_sta, false);915 ret = mt7925_mcu_add_bss_info_sta(&dev->phy, mconf->mt76.ctx,
916 link_conf, link_sta,
917 mlink_bc->wcid.idx, mlink->wcid.idx,
918 link_sta != mlink->pri_link);
919 if (ret)
920 goto out_pm;
921 } else {
922 ret = mt7925_mcu_add_bss_info_sta(&dev->phy, mconf->mt76.ctx,
923 link_conf, link_sta,
924 mlink_bc->wcid.idx, mlink->wcid.idx,
925 false);
926 if (ret)
927 goto out_pm;
928 }
899 }929 }
900 930
901 if (ieee80211_vif_is_mld(vif) &&931 if (ieee80211_vif_is_mld(vif) &&
902 link_sta == mlink->pri_link) {932 link_sta == mlink->pri_link) {
903 ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,933 ret = mt7925_mcu_sta_update(dev, link_sta, vif,
934 mlink, true,
904 MT76_STA_INFO_STATE_NONE);935 MT76_STA_INFO_STATE_NONE);
905 if (ret)936 if (ret)
906 return ret;937 goto out_pm;
907 } else if (ieee80211_vif_is_mld(vif) &&938 } else if (ieee80211_vif_is_mld(vif) &&
908 link_sta != mlink->pri_link) {939 link_sta != mlink->pri_link) {
940 struct mt792x_link_sta *pri_mlink;
941 struct mt76_wcid *pri_wcid;
942
943 /* alternative lookup via def_wcid */
944 pri_wcid = mlink->wcid.def_wcid;
945
946 pri_mlink = pri_wcid ?
947 container_of(pri_wcid, struct mt792x_link_sta, wcid) :
948 NULL;
949
950 if (WARN_ON_ONCE(!pri_mlink)) {
951 ret = -EINVAL;
952 goto out_pm;
953 }
954
909 ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif,955 ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif,
910 true, MT76_STA_INFO_STATE_ASSOC);956 pri_mlink, true,
957 MT76_STA_INFO_STATE_ASSOC);
911 if (ret)958 if (ret)
912 return ret;959 goto out_pm;
913 960
914 ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,961 ret = mt7925_mcu_sta_update(dev, link_sta, vif,
962 mlink, true,
915 MT76_STA_INFO_STATE_ASSOC);963 MT76_STA_INFO_STATE_ASSOC);
916 if (ret)964 if (ret)
917 return ret;965 goto out_pm;
918 } else {966 } else {
919 ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,967 ret = mt7925_mcu_sta_update(dev, link_sta, vif,
968 mlink, true,
920 MT76_STA_INFO_STATE_NONE);969 MT76_STA_INFO_STATE_NONE);
921 if (ret)970 if (ret)
922 return ret;971 goto out_pm;
923 }972 }
924 973
925 mt76_connac_power_save_sched(&dev->mphy, &dev->pm);974 mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
926 975
927 return 0;976 return 0;
977
978out_pm:
979 if (pm_woken)
980 mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
981out_wcid:
982 if (wcid_published) {
983 u16 idx = wcid->idx;
984
985 rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
986 mt76_wcid_cleanup(mdev, wcid);
987 mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx);
988 }
989 return ret;
990}
991
992/*
993 * Host-only unwind for sta_add_links() failures.
994 *
995 * If add_links fail due to MCU/firmware timeouts; calling the full remove
996 * path would send more firmware commands and may hang again. So only rollback
997 * host-published state here (msta->link/valid_links, dev->mt76.wcid[idx]) and
998 * free mlink objects (RCU-safe). Firmware state is left for reset/recovery.
999 */
1000static void
1001mt7925_mac_sta_unwind_links_host(struct mt792x_dev *dev,
1002 struct ieee80211_sta *sta,
1003 unsigned long links)
1004{
1005 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
1006 unsigned int link_id;
1007
1008 for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
1009 struct mt792x_link_sta *mlink;
1010 u16 idx;
1011
1012 mlink = rcu_replace_pointer(msta->link[link_id], NULL,
1013 lockdep_is_held(&dev->mt76.mutex));
1014 if (!mlink)
1015 continue;
1016
1017 msta->valid_links &= ~BIT(link_id);
1018 if (msta->deflink_id == link_id)
1019 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
1020
1021 idx = mlink->wcid.idx;
1022 rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
1023 mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);
1024 mt76_wcid_mask_clear(dev->mt76.wcid_mask, idx);
1025
1026 if (mlink != &msta->deflink)
1027 kfree_rcu(mlink, rcu_head);
1028 }
928}1029}
929 1030
930static int1031static int
@@ -932,34 +1033,50 @@ mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, · 1 unmodified line
932 struct ieee80211_sta *sta, unsigned long new_links)1033 struct ieee80211_sta *sta, unsigned long new_links)
933{1034{
934 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;1035 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
1036 unsigned long added_links = 0;
935 unsigned int link_id;1037 unsigned int link_id;
936 int err = 0;1038 int err = 0;
937 1039
938 for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {1040 for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
939 struct ieee80211_link_sta *link_sta;1041 struct ieee80211_link_sta *link_sta;
940 struct mt792x_link_sta *mlink;1042 struct mt792x_link_sta *mlink;
1043 bool is_deflink = false;
941 1044
942 if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {1045 if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
943 mlink = &msta->deflink;1046 mlink = &msta->deflink;
944 msta->deflink_id = link_id;1047 is_deflink = true;
945 } else {1048 } else {
946 mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink), GFP_KERNEL);1049 mlink = kzalloc(sizeof(*mlink), GFP_KERNEL);
947 if (!mlink) {1050 if (!mlink) {
948 err = -ENOMEM;1051 err = -ENOMEM;
949 break;1052 break;
950 }1053 }
951 }1054 }
952 1055
953 msta->valid_links |= BIT(link_id);
954 rcu_assign_pointer(msta->link[link_id], mlink);
955 mlink->sta = msta;1056 mlink->sta = msta;
956 mlink->pri_link = &sta->deflink;1057 mlink->pri_link = &sta->deflink;
957 mlink->wcid.def_wcid = &msta->deflink.wcid;1058 mlink->wcid.def_wcid = &msta->deflink.wcid;
958 1059
959 link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);1060 link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
960 mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta);1061 err = mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta, mlink);
1062 if (err) {
1063 if (!is_deflink)
1064 kfree_rcu(mlink, rcu_head);
1065 break;
1066 }
1067
1068 if (is_deflink)
1069 msta->deflink_id = link_id;
1070
1071 rcu_assign_pointer(msta->link[link_id], mlink);
1072 msta->valid_links |= BIT(link_id);
1073
1074 added_links |= BIT(link_id);
961 }1075 }
962 1076
1077 if (err && added_links)
1078 mt7925_mac_sta_unwind_links_host(dev, sta, added_links);
1079
963 return err;1080 return err;
964}1081}
965 1082
@@ -981,7 +1098,8 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, · 15 unmodified lines
981 1098
982 err = mt7925_mac_sta_add_links(dev, vif, sta, sta->valid_links);1099 err = mt7925_mac_sta_add_links(dev, vif, sta, sta->valid_links);
983 } else {1100 } else {
984 err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink);1101 err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink,
1102 &msta->deflink);
985 }1103 }
986 1104
987 return err;1105 return err;
@@ -1030,11 +1148,11 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev, · 42 unmodified lines
1030 struct mt792x_link_sta *mlink;1148 struct mt792x_link_sta *mlink;
1031 struct mt792x_sta *msta;1149 struct mt792x_sta *msta;
1032 1150
1151 mt792x_mutex_acquire(dev);
1152
1033 msta = (struct mt792x_sta *)link_sta->sta->drv_priv;1153 msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
1034 mlink = mt792x_sta_to_link(msta, link_sta->link_id);1154 mlink = mt792x_sta_to_link(msta, link_sta->link_id);
1035 1155
1036 mt792x_mutex_acquire(dev);
1037
1038 if (ieee80211_vif_is_mld(vif)) {1156 if (ieee80211_vif_is_mld(vif)) {
1039 link_conf = mt792x_vif_to_bss_conf(vif, msta->deflink_id);1157 link_conf = mt792x_vif_to_bss_conf(vif, msta->deflink_id);
1040 } else {1158 } else {
@@ -1055,7 +1173,8 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev, · 14 unmodified lines
1055 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);1173 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
1056 memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac));1174 memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac));
1057 1175
1058 mt7925_mcu_sta_update(dev, link_sta, vif, true, MT76_STA_INFO_STATE_ASSOC);1176 mt7925_mcu_sta_update(dev, link_sta, vif, mlink, true,
1177 MT76_STA_INFO_STATE_ASSOC);
1059 1178
1060 mt792x_mutex_release(dev);1179 mt792x_mutex_release(dev);
1061}1180}
@@ -1083,23 +1202,21 @@ EXPORT_SYMBOL_GPL(mt7925_mac_sta_event); · 21 unmodified lines
1083 1202
1084static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,1203static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
1085 struct ieee80211_vif *vif,1204 struct ieee80211_vif *vif,
1086 struct ieee80211_link_sta *link_sta)1205 struct ieee80211_link_sta *link_sta,
1206 struct mt792x_link_sta *mlink)
1087{1207{
1088 struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);1208 struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1209 struct mt76_wcid *wcid = &mlink->wcid;
1089 struct ieee80211_bss_conf *link_conf;1210 struct ieee80211_bss_conf *link_conf;
1090 u8 link_id = link_sta->link_id;1211 u8 link_id = link_sta->link_id;
1091 struct mt792x_link_sta *mlink;1212 u16 idx = wcid->idx;
1092 struct mt792x_sta *msta;
1093
1094 msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
1095 mlink = mt792x_sta_to_link(msta, link_id);
1096 1213
1097 mt7925_roc_abort_sync(dev);1214 mt7925_roc_abort_sync(dev);
1098 1215
1099 mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid);1216 mt76_connac_free_pending_tx_skbs(&dev->pm, wcid);
1100 mt76_connac_pm_wake(&dev->mphy, &dev->pm);1217 mt76_connac_pm_wake(&dev->mphy, &dev->pm);
1101 1218
1102 mt7925_mcu_sta_update(dev, link_sta, vif, false,1219 mt7925_mcu_sta_update(dev, link_sta, vif, mlink, false,
1103 MT76_STA_INFO_STATE_NONE);1220 MT76_STA_INFO_STATE_NONE);
1104 mt7925_mac_wtbl_update(dev, mlink->wcid.idx,1221 mt7925_mac_wtbl_update(dev, mlink->wcid.idx,
1105 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);1222 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -1123,6 +1240,10 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev, · 17 unmodified lines
1123 list_del_init(&mlink->wcid.poll_list);1240 list_del_init(&mlink->wcid.poll_list);
1124 spin_unlock_bh(&mdev->sta_poll_lock);1241 spin_unlock_bh(&mdev->sta_poll_lock);
1125 1242
1243 rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
1244 mt76_wcid_cleanup(mdev, wcid);
1245 mt76_wcid_mask_clear(mdev->wcid_mask, idx);
1246
1126 mt76_connac_power_save_sched(&dev->mphy, &dev->pm);1247 mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
1127}1248}
1128 1249
@@ -1132,7 +1253,6 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, · 3 unmodified lines
1132{1253{
1133 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;1254 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
1134 struct mt76_dev *mdev = &dev->mt76;1255 struct mt76_dev *mdev = &dev->mt76;
1135 struct mt76_wcid *wcid;
1136 unsigned int link_id;1256 unsigned int link_id;
1137 1257
1138 /* clean up bss before starec */1258 /* clean up bss before starec */
@@ -1171,22 +1291,19 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, · 32 unmodified lines
1171 if (!link_sta)1291 if (!link_sta)
1172 continue;1292 continue;
1173 1293
1174 mlink = mt792x_sta_to_link(msta, link_id);1294 mlink = rcu_replace_pointer(msta->link[link_id], NULL,
1295 lockdep_is_held(&mdev->mutex));
1175 if (!mlink)1296 if (!mlink)
1176 continue;1297 continue;
1177 1298
1178 mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta);
1179
1180 wcid = &mlink->wcid;
1181 rcu_assign_pointer(msta->link[link_id], NULL);
1182 msta->valid_links &= ~BIT(link_id);1299 msta->valid_links &= ~BIT(link_id);
1183 mlink->sta = NULL;1300 mlink->sta = NULL;
1184 mlink->pri_link = NULL;1301 mlink->pri_link = NULL;
1185 1302
1186 if (link_sta != mlink->pri_link) {1303 mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta, mlink);
1187 mt76_wcid_cleanup(mdev, wcid);1304
1188 mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx);1305 if (mlink != &msta->deflink)
1189 }1306 kfree_rcu(mlink, rcu_head);
1190 1307
1191 if (msta->deflink_id == link_id)1308 if (msta->deflink_id == link_id)
1192 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;1309 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
@@ -1323,10 +1440,18 @@ void mt7925_mlo_pm_work(struct work_struct *work) · 130 unmodified lines
1323void mt7925_scan_work(struct work_struct *work)1440void mt7925_scan_work(struct work_struct *work)
1324{1441{
1325 struct mt792x_phy *phy;1442 struct mt792x_phy *phy;
1443 struct mt792x_dev *dev;
1444 struct mt76_connac_pm *pm;
1326 1445
1327 phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,1446 phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,
1328 scan_work.work);1447 scan_work.work);
1329 1448
1449 dev = phy->dev;
1450 pm = &dev->pm;
1451
1452 if (pm->suspended)
1453 return;
1454
1330 while (true) {1455 while (true) {
1331 struct sk_buff *skb;1456 struct sk_buff *skb;
1332 struct tlv *tlv;1457 struct tlv *tlv;
@@ -1544,8 +1669,10 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, · 211 unmodified lines
1544 valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0);1669 valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0);
1545 1670
1546 for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {1671 for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
1672 struct mt792x_bss_conf *mconf;
1547 struct mt792x_link_sta *mlink;1673 struct mt792x_link_sta *mlink;
1548 1674
1675 mconf = mt792x_vif_to_link(mvif, i);
1549 mlink = mt792x_sta_to_link(msta, i);1676 mlink = mt792x_sta_to_link(msta, i);
1550 1677
1551 if (enabled)1678 if (enabled)
@@ -1556,7 +1683,7 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, · 4 unmodified lines
1556 if (!mlink->wcid.sta)1683 if (!mlink->wcid.sta)
1557 continue;1684 continue;
1558 1685
1559 mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i);1686 mt7925_mcu_wtbl_update_hdr_trans(dev, vif, mconf, mlink);
1560 }1687 }
1561 1688
1562 mt792x_mutex_release(dev);1689 mt792x_mutex_release(dev);
@@ -1716,7 +1843,8 @@ mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 153 unmodified lines
1716 if (err)1843 if (err)
1717 goto out;1844 goto out;
1718 1845
1719 err = mt7925_mcu_sta_update(dev, NULL, vif, true,1846 err = mt7925_mcu_sta_update(dev, NULL, vif,
1847 &mvif->sta.deflink, true,
1720 MT76_STA_INFO_STATE_NONE);1848 MT76_STA_INFO_STATE_NONE);
1721out:1849out:
1722 mt792x_mutex_release(dev);1850 mt792x_mutex_release(dev);
@@ -1749,6 +1877,10 @@ static int · 26 unmodified lines
1749mt7925_add_chanctx(struct ieee80211_hw *hw,1877mt7925_add_chanctx(struct ieee80211_hw *hw,
1750 struct ieee80211_chanctx_conf *ctx)1878 struct ieee80211_chanctx_conf *ctx)
1751{1879{
1880 struct mt792x_dev *dev = mt792x_hw_dev(hw);
1881
1882 dev->new_ctx = ctx;
1883
1752 return 0;1884 return 0;
1753}1885}
1754 1886
@@ -1756,6 +1888,11 @@ static void · 1 unmodified line
1756mt7925_remove_chanctx(struct ieee80211_hw *hw,1888mt7925_remove_chanctx(struct ieee80211_hw *hw,
1757 struct ieee80211_chanctx_conf *ctx)1889 struct ieee80211_chanctx_conf *ctx)
1758{1890{
1891 struct mt792x_dev *dev = mt792x_hw_dev(hw);
1892
1893 if (dev->new_ctx == ctx)
1894 dev->new_ctx = NULL;
1895
1759}1896}
1760 1897
1761static void1898static void
@@ -1850,7 +1987,8 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw, · 88 unmodified lines
1850 mt792x_mutex_acquire(dev);1987 mt792x_mutex_acquire(dev);
1851 1988
1852 if (changed & BSS_CHANGED_ASSOC) {1989 if (changed & BSS_CHANGED_ASSOC) {
1853 mt7925_mcu_sta_update(dev, NULL, vif, true,1990 mt7925_mcu_sta_update(dev, NULL, vif,
1991 &mvif->sta.deflink, true,
1854 MT76_STA_INFO_STATE_ASSOC);1992 MT76_STA_INFO_STATE_ASSOC);
1855 mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);1993 mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
1856 1994
@@ -1894,10 +2032,8 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw, · 37 unmodified lines
1894 struct mt792x_phy *phy = mt792x_hw_phy(hw);2032 struct mt792x_phy *phy = mt792x_hw_phy(hw);
1895 struct mt792x_dev *dev = mt792x_hw_dev(hw);2033 struct mt792x_dev *dev = mt792x_hw_dev(hw);
1896 struct mt792x_bss_conf *mconf;2034 struct mt792x_bss_conf *mconf;
1897 struct ieee80211_bss_conf *link_conf;
1898 2035
1899 mconf = mt792x_vif_to_link(mvif, info->link_id);2036 mconf = mt792x_vif_to_link(mvif, info->link_id);
1900 link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);
1901 2037
1902 mt792x_mutex_acquire(dev);2038 mt792x_mutex_acquire(dev);
1903 2039
@@ -1939,10 +2075,6 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw, · 35 unmodified lines
1939 mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS;2075 mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS;
1940 }2076 }
1941 2077
1942 if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)
1943 mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76,
1944 link_conf, NULL);
1945
1946 if (changed & BSS_CHANGED_CQM)2078 if (changed & BSS_CHANGED_CQM)
1947 mt7925_mcu_set_rssimonitor(dev, vif);2079 mt7925_mcu_set_rssimonitor(dev, vif);
1948 2080
@@ -2144,6 +2276,11 @@ static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw, · 195 unmodified lines
2144 mctx->bss_conf = NULL;2276 mctx->bss_conf = NULL;
2145 mconf->mt76.ctx = NULL;2277 mconf->mt76.ctx = NULL;
2146 mutex_unlock(&dev->mt76.mutex);2278 mutex_unlock(&dev->mt76.mutex);
2279
2280 if (link_conf->csa_active) {
2281 timer_delete_sync(&mvif->csa_timer);
2282 cancel_work_sync(&mvif->csa_work);
2283 }
2147}2284}
2148 2285
2149static void mt7925_rfkill_poll(struct ieee80211_hw *hw)2286static void mt7925_rfkill_poll(struct ieee80211_hw *hw)
@@ -2158,6 +2295,121 @@ static void mt7925_rfkill_poll(struct ieee80211_hw *hw) · 8 unmodified lines
2158 wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0);2295 wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0);
2159}2296}
2160 2297
2298static int mt7925_switch_vif_chanctx(struct ieee80211_hw *hw,
2299 struct ieee80211_vif_chanctx_switch *vifs,
2300 int n_vifs,
2301 enum ieee80211_chanctx_switch_mode mode)
2302{
2303 return mt7925_assign_vif_chanctx(hw, vifs->vif, vifs->link_conf,
2304 vifs->new_ctx);
2305}
2306
2307void mt7925_csa_work(struct work_struct *work)
2308{
2309 struct mt792x_vif *mvif;
2310 struct mt792x_dev *dev;
2311 struct ieee80211_vif *vif;
2312 struct ieee80211_bss_conf *link_conf;
2313 struct mt792x_bss_conf *mconf;
2314 u8 link_id, roc_rtype;
2315 int ret = 0;
2316
2317 mvif = (struct mt792x_vif *)container_of(work, struct mt792x_vif,
2318 csa_work);
2319 dev = mvif->phy->dev;
2320 vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
2321
2322 if (ieee80211_vif_is_mld(vif))
2323 return;
2324
2325 if (!dev->new_ctx)
2326 return;
2327
2328 link_id = 0;
2329 mconf = &mvif->bss_conf;
2330 link_conf = &vif->bss_conf;
2331 roc_rtype = MT7925_ROC_REQ_JOIN;
2332
2333 mt792x_mutex_acquire(dev);
2334 ret = mt7925_set_roc(mvif->phy, mconf, dev->new_ctx->def.chan,
2335 4000, roc_rtype);
2336 mt792x_mutex_release(dev);
2337 if (!ret) {
2338 mt792x_mutex_acquire(dev);
2339 ret = mt7925_mcu_set_chctx(mvif->phy->mt76, &mconf->mt76, link_conf,
2340 dev->new_ctx);
2341 mt792x_mutex_release(dev);
2342
2343 mt7925_abort_roc(mvif->phy, mconf);
2344 }
2345
2346 ieee80211_chswitch_done(vif, !ret, link_id);
2347}
2348
2349static int mt7925_pre_channel_switch(struct ieee80211_hw *hw,
2350 struct ieee80211_vif *vif,
2351 struct ieee80211_channel_switch *chsw)
2352{
2353 if (ieee80211_vif_is_mld(vif))
2354 return -EOPNOTSUPP;
2355
2356 if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
2357 return -EOPNOTSUPP;
2358
2359 if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef,
2360 IEEE80211_CHAN_DISABLED))
2361 return -EOPNOTSUPP;
2362
2363 return 0;
2364}
2365
2366static void mt7925_channel_switch(struct ieee80211_hw *hw,
2367 struct ieee80211_vif *vif,
2368 struct ieee80211_channel_switch *chsw)
2369{
2370 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
2371 u16 beacon_interval;
2372
2373 if (ieee80211_vif_is_mld(vif))
2374 return;
2375
2376 beacon_interval = vif->bss_conf.beacon_int;
2377
2378 mvif->csa_timer.expires = TU_TO_EXP_TIME(beacon_interval * chsw->count);
2379 add_timer(&mvif->csa_timer);
2380}
2381
2382static void mt7925_abort_channel_switch(struct ieee80211_hw *hw,
2383 struct ieee80211_vif *vif,
2384 struct ieee80211_bss_conf *link_conf)
2385{
2386 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
2387
2388 timer_delete_sync(&mvif->csa_timer);
2389 cancel_work_sync(&mvif->csa_work);
2390}
2391
2392static void mt7925_channel_switch_rx_beacon(struct ieee80211_hw *hw,
2393 struct ieee80211_vif *vif,
2394 struct ieee80211_channel_switch *chsw)
2395{
2396 struct mt792x_dev *dev = mt792x_hw_dev(hw);
2397 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
2398 u16 beacon_interval;
2399
2400 if (ieee80211_vif_is_mld(vif))
2401 return;
2402
2403 beacon_interval = vif->bss_conf.beacon_int;
2404
2405 if (cfg80211_chandef_identical(&chsw->chandef,
2406 &dev->new_ctx->def) &&
2407 chsw->count) {
2408 mod_timer(&mvif->csa_timer,
2409 TU_TO_EXP_TIME(beacon_interval * chsw->count));
2410 }
2411}
2412
2161const struct ieee80211_ops mt7925_ops = {2413const struct ieee80211_ops mt7925_ops = {
2162 .tx = mt792x_tx,2414 .tx = mt792x_tx,
2163 .start = mt7925_start,2415 .start = mt7925_start,
@@ -2221,6 +2473,12 @@ const struct ieee80211_ops mt7925_ops = { · 57 unmodified lines
2221 .change_vif_links = mt7925_change_vif_links,2473 .change_vif_links = mt7925_change_vif_links,
2222 .change_sta_links = mt7925_change_sta_links,2474 .change_sta_links = mt7925_change_sta_links,
2223 .rfkill_poll = mt7925_rfkill_poll,2475 .rfkill_poll = mt7925_rfkill_poll,
2476
2477 .switch_vif_chanctx = mt7925_switch_vif_chanctx,
2478 .pre_channel_switch = mt7925_pre_channel_switch,
2479 .channel_switch = mt7925_channel_switch,
2480 .abort_channel_switch = mt7925_abort_channel_switch,
2481 .channel_switch_rx_beacon = mt7925_channel_switch_rx_beacon,
2224};2482};
2225EXPORT_SYMBOL_GPL(mt7925_ops);2483EXPORT_SYMBOL_GPL(mt7925_ops);
2226 2484
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c+106−88
@@ -1066,9 +1066,8 @@ EXPORT_SYMBOL_GPL(mt7925_run_firmware); · 1065 unmodified lines
1066static void1066static void
1067mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,1067mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
1068 struct ieee80211_vif *vif,1068 struct ieee80211_vif *vif,
1069 struct ieee80211_link_sta *link_sta)1069 struct mt792x_link_sta *mlink)
1070{1070{
1071 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
1072 struct sta_rec_hdr_trans *hdr_trans;1071 struct sta_rec_hdr_trans *hdr_trans;
1073 struct mt76_wcid *wcid;1072 struct mt76_wcid *wcid;
1074 struct tlv *tlv;1073 struct tlv *tlv;
@@ -1082,19 +1081,11 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb, · 7 unmodified lines
1082 else1081 else
1083 hdr_trans->from_ds = true;1082 hdr_trans->from_ds = true;
1084 1083
1085 if (link_sta) {1084 if (WARN_ON_ONCE(!mlink))
1086 struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
1087 struct mt792x_link_sta *mlink;
1088
1089 mlink = mt792x_sta_to_link(msta, link_sta->link_id);
1090 wcid = &mlink->wcid;
1091 } else {
1092 wcid = &mvif->sta.deflink.wcid;
1093 }
1094
1095 if (!wcid)
1096 return;1085 return;
1097 1086
1087 wcid = &mlink->wcid;
1088
1098 hdr_trans->dis_rx_hdr_tran = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);1089 hdr_trans->dis_rx_hdr_tran = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
1099 if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {1090 if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {
1100 hdr_trans->to_ds = true;1091 hdr_trans->to_ds = true;
@@ -1104,30 +1095,18 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb, · 3 unmodified lines
1104 1095
1105int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,1096int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
1106 struct ieee80211_vif *vif,1097 struct ieee80211_vif *vif,
1107 struct ieee80211_sta *sta,1098 struct mt792x_bss_conf *mconf,
1108 int link_id)1099 struct mt792x_link_sta *mlink)
1109{1100{
1110 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
1111 struct ieee80211_link_sta *link_sta = sta ? &sta->deflink : NULL;
1112 struct mt792x_link_sta *mlink;
1113 struct mt792x_bss_conf *mconf;
1114 struct mt792x_sta *msta;
1115 struct sk_buff *skb;1101 struct sk_buff *skb;
1116 1102
1117 msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta;
1118
1119 mlink = mt792x_sta_to_link(msta, link_id);
1120 link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
1121 mconf = mt792x_vif_to_link(mvif, link_id);
1122
1123 skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mconf->mt76,1103 skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mconf->mt76,
1124 &mlink->wcid,1104 &mlink->wcid,
1125 MT7925_STA_UPDATE_MAX_SIZE);1105 MT7925_STA_UPDATE_MAX_SIZE);
1126 if (IS_ERR(skb))1106 if (IS_ERR(skb))
1127 return PTR_ERR(skb);1107 return PTR_ERR(skb);
1128 1108
1129 /* starec hdr trans */1109 mt7925_mcu_sta_hdr_trans_tlv(skb, vif, mlink);
1130 mt7925_mcu_sta_hdr_trans_tlv(skb, vif, link_sta);
1131 return mt76_mcu_skb_send_msg(&dev->mt76, skb,1110 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
1132 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);1111 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
1133}1112}
@@ -1288,14 +1267,16 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, · 154 unmodified lines
1288 return PTR_ERR(skb);1267 return PTR_ERR(skb);
1289 1268
1290 ret = mt7925_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd, msta);1269 ret = mt7925_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd, msta);
1291 if (ret)1270 if (ret) {
1271 dev_kfree_skb(skb);
1292 return ret;1272 return ret;
1273 }
1293 1274
1294 return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);1275 return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
1295}1276}
1296 1277
1297int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,1278int mt7925_mcu_set_mlo_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
1298 int duration, u8 token_id)1279 u16 sel_links, int duration, u8 token_id)
1299{1280{
1300 struct mt792x_vif *mvif = mconf->vif;1281 struct mt792x_vif *mvif = mconf->vif;
1301 struct ieee80211_vif *vif = container_of((void *)mvif,1282 struct ieee80211_vif *vif = container_of((void *)mvif,
@@ -1330,6 +1311,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, · 28 unmodified lines
1330 .roc[1].len = cpu_to_le16(sizeof(struct roc_acquire_tlv))1311 .roc[1].len = cpu_to_le16(sizeof(struct roc_acquire_tlv))
1331 };1312 };
1332 1313
1314 struct wiphy *wiphy = phy->mt76->hw->wiphy;
1315
1333 if (!mconf || hweight16(vif->valid_links) < 2 ||1316 if (!mconf || hweight16(vif->valid_links) < 2 ||
1334 hweight16(sel_links) != 2)1317 hweight16(sel_links) != 2)
1335 return -EPERM;1318 return -EPERM;
@@ -1352,7 +1335,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, · 16 unmodified lines
1352 is_AG_band |= links[i].chan->band == NL80211_BAND_2GHZ;1335 is_AG_band |= links[i].chan->band == NL80211_BAND_2GHZ;
1353 }1336 }
1354 1337
1355 if (vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP)1338 if (!(wiphy->iftype_ext_capab[0].mld_capa_and_ops &
1339 IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS))
1356 type = is_AG_band ? MT7925_ROC_REQ_MLSR_AG :1340 type = is_AG_band ? MT7925_ROC_REQ_MLSR_AG :
1357 MT7925_ROC_REQ_MLSR_AA;1341 MT7925_ROC_REQ_MLSR_AA;
1358 else1342 else
@@ -1721,10 +1705,9 @@ mt7925_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta) · 362 unmodified lines
1721static void1705static void
1722mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb,1706mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb,
1723 struct ieee80211_vif *vif,1707 struct ieee80211_vif *vif,
1724 struct ieee80211_link_sta *link_sta)1708 struct ieee80211_link_sta *link_sta,
1709 struct mt792x_link_sta *mlink)
1725{1710{
1726 struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
1727 struct mt792x_link_sta *mlink;
1728 struct sta_rec_amsdu *amsdu;1711 struct sta_rec_amsdu *amsdu;
1729 struct tlv *tlv;1712 struct tlv *tlv;
1730 1713
@@ -1740,7 +1723,6 @@ mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb, · 9 unmodified lines
1740 amsdu->max_amsdu_num = 8;1723 amsdu->max_amsdu_num = 8;
1741 amsdu->amsdu_en = true;1724 amsdu->amsdu_en = true;
1742 1725
1743 mlink = mt792x_sta_to_link(msta, link_sta->link_id);
1744 mlink->wcid.amsdu = true;1726 mlink->wcid.amsdu = true;
1745 1727
1746 switch (link_sta->agg.max_amsdu_len) {1728 switch (link_sta->agg.max_amsdu_len) {
@@ -1911,36 +1893,53 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb, · 164 unmodified lines
1911 1893
1912static void1894static void
1913mt7925_mcu_sta_mld_tlv(struct sk_buff *skb,1895mt7925_mcu_sta_mld_tlv(struct sk_buff *skb,
1914 struct ieee80211_vif *vif, struct ieee80211_sta *sta)1896 struct ieee80211_vif *vif,
1897 struct ieee80211_sta *sta,
1898 struct mt792x_bss_conf *mconf,
1899 struct mt792x_link_sta *mlink)
1915{1900{
1916 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1901 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
1917 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;1902 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
1918 unsigned long valid = mvif->valid_links;1903 struct mt792x_dev *dev = mvif->phy->dev;
1919 struct mt792x_bss_conf *mconf;1904 struct mt792x_bss_conf *mconf_pri;
1920 struct mt792x_link_sta *mlink;
1921 struct sta_rec_mld *mld;1905 struct sta_rec_mld *mld;
1922 struct tlv *tlv;1906 struct tlv *tlv;
1923 int i, cnt = 0;1907 u8 cnt = 0;
1908
1909 /* Primary link always uses driver's deflink WCID. */
1910 mconf_pri = (msta->deflink_id != IEEE80211_LINK_UNSPECIFIED) ?
1911 mt792x_vif_to_link(mvif, msta->deflink_id) : NULL;
1912
1913 /* If caller is operating on deflink, reuse its mconf as primary. */
1914 if (!mconf_pri && mlink == &msta->deflink)
1915 mconf_pri = mconf;
1916
1917 if (!mconf_pri) {
1918 dev_warn_ratelimited(dev->mt76.dev,
1919 "mt7925: MLD_TLV_LINK skip (no primary mconf) sta=%pM\n",
1920 sta->addr);
1921 return;
1922 }
1924 1923
1925 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD, sizeof(*mld));1924 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD, sizeof(*mld));
1926 mld = (struct sta_rec_mld *)tlv;1925 mld = (struct sta_rec_mld *)tlv;
1927 memcpy(mld->mac_addr, sta->addr, ETH_ALEN);1926 memcpy(mld->mac_addr, sta->addr, ETH_ALEN);
1927
1928 mld->primary_id = cpu_to_le16(msta->deflink.wcid.idx);1928 mld->primary_id = cpu_to_le16(msta->deflink.wcid.idx);
1929 mld->wlan_id = cpu_to_le16(msta->deflink.wcid.idx);1929 mld->wlan_id = cpu_to_le16(msta->deflink.wcid.idx);
1930 mld->link_num = min_t(u8, hweight16(mvif->valid_links), 2);
1931 1930
1932 for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {1931 /* Always encode primary link first. */
1933 if (cnt == mld->link_num)1932 mld->link[cnt].wlan_id = cpu_to_le16(msta->deflink.wcid.idx);
1934 break;1933 mld->link[cnt++].bss_idx = mconf_pri->mt76.idx;
1935 1934
1936 mconf = mt792x_vif_to_link(mvif, i);1935 /* Optionally encode the currently-updated secondary link. */
1937 mlink = mt792x_sta_to_link(msta, i);1936 if (mlink && mlink != &msta->deflink && mconf) {
1937 mld->secondary_id = cpu_to_le16(mlink->wcid.idx);
1938 mld->link[cnt].wlan_id = cpu_to_le16(mlink->wcid.idx);1938 mld->link[cnt].wlan_id = cpu_to_le16(mlink->wcid.idx);
1939 mld->link[cnt++].bss_idx = mconf->mt76.idx;1939 mld->link[cnt++].bss_idx = mconf->mt76.idx;
1940
1941 if (mlink != &msta->deflink)
1942 mld->secondary_id = cpu_to_le16(mlink->wcid.idx);
1943 }1940 }
1941
1942 mld->link_num = cnt;
1944}1943}
1945 1944
1946static void1945static void
@@ -1961,10 +1960,12 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 14 unmodified lines
1961 struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv;1960 struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv;
1962 struct mt76_dev *dev = phy->dev;1961 struct mt76_dev *dev = phy->dev;
1963 struct mt792x_bss_conf *mconf;1962 struct mt792x_bss_conf *mconf;
1963 struct mt792x_link_sta *mlink;
1964 struct sk_buff *skb;1964 struct sk_buff *skb;
1965 int conn_state;1965 int conn_state;
1966 1966
1967 mconf = mt792x_vif_to_link(mvif, info->wcid->link_id);1967 mconf = mt792x_vif_to_link(mvif, info->wcid->link_id);
1968 mlink = container_of(info->wcid, struct mt792x_link_sta, wcid);
1968 1969
1969 skb = __mt76_connac_mcu_alloc_sta_req(dev, &mconf->mt76, info->wcid,1970 skb = __mt76_connac_mcu_alloc_sta_req(dev, &mconf->mt76, info->wcid,
1970 MT7925_STA_UPDATE_MAX_SIZE);1971 MT7925_STA_UPDATE_MAX_SIZE);
@@ -1982,7 +1983,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 11 unmodified lines
1982 mt7925_mcu_sta_ht_tlv(skb, info->link_sta);1983 mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
1983 mt7925_mcu_sta_vht_tlv(skb, info->link_sta);1984 mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
1984 mt76_connac_mcu_sta_uapsd(skb, info->vif, info->link_sta->sta);1985 mt76_connac_mcu_sta_uapsd(skb, info->vif, info->link_sta->sta);
1985 mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta);1986 mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta, mlink);
1986 mt7925_mcu_sta_he_tlv(skb, info->link_sta);1987 mt7925_mcu_sta_he_tlv(skb, info->link_sta);
1987 mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta);1988 mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta);
1988 mt7925_mcu_sta_eht_tlv(skb, info->link_sta);1989 mt7925_mcu_sta_eht_tlv(skb, info->link_sta);
@@ -1993,7 +1994,10 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 4 unmodified lines
1993 info->state);1994 info->state);
1994 1995
1995 if (info->state != MT76_STA_INFO_STATE_NONE) {1996 if (info->state != MT76_STA_INFO_STATE_NONE) {
1996 mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta);1997 mt7925_mcu_sta_mld_tlv(skb, info->vif,
1998 info->link_sta->sta,
1999 mconf, mlink);
2000
1997 mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta);2001 mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta);
1998 }2002 }
1999 }2003 }
@@ -2003,7 +2007,10 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 3 unmodified lines
2003 mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF,2007 mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF,
2004 sizeof(struct tlv));2008 sizeof(struct tlv));
2005 } else {2009 } else {
2006 mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);2010 if (!info->link_sta)
2011 mlink = &mvif->sta.deflink;
2012
2013 mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, mlink);
2007 }2014 }
2008 2015
2009 return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);2016 return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
@@ -2011,7 +2018,9 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 1 unmodified line
2011 2018
2012int mt7925_mcu_sta_update(struct mt792x_dev *dev,2019int mt7925_mcu_sta_update(struct mt792x_dev *dev,
2013 struct ieee80211_link_sta *link_sta,2020 struct ieee80211_link_sta *link_sta,
2014 struct ieee80211_vif *vif, bool enable,2021 struct ieee80211_vif *vif,
2022 struct mt792x_link_sta *mlink,
2023 bool enable,
2015 enum mt76_sta_info_state state)2024 enum mt76_sta_info_state state)
2016{2025{
2017 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;2026 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
@@ -2026,14 +2035,8 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev, · 8 unmodified lines
2026 .offload_fw = true,2035 .offload_fw = true,
2027 .rcpi = to_rcpi(rssi),2036 .rcpi = to_rcpi(rssi),
2028 };2037 };
2029 struct mt792x_sta *msta;
2030 struct mt792x_link_sta *mlink;
2031 2038
2032 if (link_sta) {2039 info.wcid = &mlink->wcid;
2033 msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
2034 mlink = mt792x_sta_to_link(msta, link_sta->link_id);
2035 }
2036 info.wcid = link_sta ? &mlink->wcid : &mvif->sta.deflink.wcid;
2037 info.newly = state != MT76_STA_INFO_STATE_ASSOC;2040 info.newly = state != MT76_STA_INFO_STATE_ASSOC;
2038 2041
2039 return mt7925_mcu_sta_cmd(&dev->mphy, &info);2042 return mt7925_mcu_sta_cmd(&dev->mphy, &info);
@@ -2470,7 +2473,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, · 430 unmodified lines
2470 struct ieee80211_bss_conf *link_conf,2473 struct ieee80211_bss_conf *link_conf,
2471 struct ieee80211_link_sta *link_sta,2474 struct ieee80211_link_sta *link_sta,
2472 struct ieee80211_chanctx_conf *ctx,2475 struct ieee80211_chanctx_conf *ctx,
2473 struct mt76_phy *phy, u16 wlan_idx,2476 struct mt76_phy *phy,
2477 u16 bmc_tx_wlan_idx,
2478 u16 sta_wlan_idx,
2474 bool enable)2479 bool enable)
2475{2480{
2476 struct ieee80211_vif *vif = link_conf->vif;2481 struct ieee80211_vif *vif = link_conf->vif;
@@ -2479,7 +2484,6 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, · 2 unmodified lines
2479 &link_conf->chanreq.oper;2484 &link_conf->chanreq.oper;
2480 enum nl80211_band band = chandef->chan->band;2485 enum nl80211_band band = chandef->chan->band;
2481 struct mt76_connac_bss_basic_tlv *basic_req;2486 struct mt76_connac_bss_basic_tlv *basic_req;
2482 struct mt792x_link_sta *mlink;
2483 struct tlv *tlv;2487 struct tlv *tlv;
2484 int conn_type;2488 int conn_type;
2485 u8 idx;2489 u8 idx;
@@ -2503,20 +2507,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, · 17 unmodified lines
2503 basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, link_sta);2507 basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, link_sta);
2504 basic_req->bcn_interval = cpu_to_le16(link_conf->beacon_int);2508 basic_req->bcn_interval = cpu_to_le16(link_conf->beacon_int);
2505 basic_req->dtim_period = link_conf->dtim_period;2509 basic_req->dtim_period = link_conf->dtim_period;
2506 basic_req->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);2510 basic_req->bmc_tx_wlan_idx = cpu_to_le16(bmc_tx_wlan_idx);
2507 basic_req->link_idx = mconf->mt76.idx;2511 basic_req->link_idx = mconf->mt76.idx;
2508 2512 basic_req->sta_idx = cpu_to_le16(sta_wlan_idx);
2509 if (link_sta) {
2510 struct mt792x_sta *msta;
2511
2512 msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
2513 mlink = mt792x_sta_to_link(msta, link_sta->link_id);
2514
2515 } else {
2516 mlink = &mconf->vif->sta.deflink;
2517 }
2518
2519 basic_req->sta_idx = cpu_to_le16(mlink->wcid.idx);
2520 basic_req->omac_idx = mconf->mt76.omac_idx;2513 basic_req->omac_idx = mconf->mt76.omac_idx;
2521 basic_req->band_idx = mconf->mt76.band_idx;2514 basic_req->band_idx = mconf->mt76.band_idx;
2522 basic_req->wmm_idx = mconf->mt76.wmm_idx;2515 basic_req->wmm_idx = mconf->mt76.wmm_idx;
@@ -2823,16 +2816,16 @@ void mt7925_mcu_del_dev(struct mt76_dev *mdev, · 300 unmodified lines
2823 &dev_req, sizeof(dev_req), true);2816 &dev_req, sizeof(dev_req), true);
2824}2817}
2825 2818
2826int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,2819int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
2827 struct ieee80211_chanctx_conf *ctx,2820 struct ieee80211_chanctx_conf *ctx,
2828 struct ieee80211_bss_conf *link_conf,2821 struct ieee80211_bss_conf *link_conf,
2829 struct ieee80211_link_sta *link_sta,2822 struct ieee80211_link_sta *link_sta,
2830 int enable)2823 u16 bmc_tx_wlan_idx,
2824 u16 sta_wlan_idx,
2825 int enable)
2831{2826{
2832 struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
2833 struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);2827 struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
2834 struct mt792x_dev *dev = phy->dev;2828 struct mt792x_dev *dev = phy->dev;
2835 struct mt792x_link_sta *mlink_bc;
2836 struct sk_buff *skb;2829 struct sk_buff *skb;
2837 2830
2838 skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mconf->mt76,2831 skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mconf->mt76,
@@ -2840,11 +2833,9 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy, · 1 unmodified line
2840 if (IS_ERR(skb))2833 if (IS_ERR(skb))
2841 return PTR_ERR(skb);2834 return PTR_ERR(skb);
2842 2835
2843 mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
2844
2845 /* bss_basic must be first */2836 /* bss_basic must be first */
2846 mt7925_mcu_bss_basic_tlv(skb, link_conf, link_sta, ctx, phy->mt76,2837 mt7925_mcu_bss_basic_tlv(skb, link_conf, link_sta, ctx, phy->mt76,
2847 mlink_bc->wcid.idx, enable);2838 bmc_tx_wlan_idx, sta_wlan_idx, enable);
2848 mt7925_mcu_bss_sec_tlv(skb, link_conf);2839 mt7925_mcu_bss_sec_tlv(skb, link_conf);
2849 mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, link_conf);2840 mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, link_conf);
2850 mt7925_mcu_bss_qos_tlv(skb, link_conf);2841 mt7925_mcu_bss_qos_tlv(skb, link_conf);
@@ -2865,6 +2856,33 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy, · 14 unmodified lines
2865 MCU_UNI_CMD(BSS_INFO_UPDATE), true);2856 MCU_UNI_CMD(BSS_INFO_UPDATE), true);
2866}2857}
2867 2858
2859int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
2860 struct ieee80211_chanctx_conf *ctx,
2861 struct ieee80211_bss_conf *link_conf,
2862 struct ieee80211_link_sta *link_sta,
2863 int enable)
2864{
2865 struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
2866 struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
2867 struct mt792x_link_sta *mlink_bc;
2868 struct mt792x_link_sta *mlink;
2869
2870 mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
2871
2872 if (link_sta) {
2873 struct mt792x_sta *msta = (void *)link_sta->sta->drv_priv;
2874
2875 mlink = mt792x_sta_to_link(msta, link_sta->link_id);
2876 if (WARN_ON(!mlink))
2877 return -EINVAL;
2878 } else {
2879 mlink = &mconf->vif->sta.deflink;
2880 }
2881
2882 return mt7925_mcu_add_bss_info_sta(phy, ctx, link_conf, link_sta,
2883 mlink_bc->wcid.idx, mlink->wcid.idx, enable);
2884}
2885
2868int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)2886int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
2869{2887{
2870 struct mt76_dev *mdev = phy->dev;2888 struct mt76_dev *mdev = phy->dev;
@@ -3375,7 +3393,6 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, · 504 unmodified lines
3375 u8 rsvd[64];3393 u8 rsvd[64];
3376 } __packed req = {3394 } __packed req = {
3377 .tag = cpu_to_le16(0x3),3395 .tag = cpu_to_le16(0x3),
3378 .len = cpu_to_le16(sizeof(req) - 4),
3379 3396
3380 .idx = idx,3397 .idx = idx,
3381 .env = env_cap,3398 .env = env_cap,
@@ -3404,6 +3421,7 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, · 22 unmodified lines
3404 memcpy(req.type, rule->type, 2);3421 memcpy(req.type, rule->type, 2);
3405 3422
3406 req.size = cpu_to_le16(seg->len);3423 req.size = cpu_to_le16(seg->len);
3424 req.len = cpu_to_le16(sizeof(req) + seg->len - 4);
3407 dev->phy.clc_chan_conf = clc->ver == 1 ? 0xff : rule->flag;3425 dev->phy.clc_chan_conf = clc->ver == 1 ? 0xff : rule->flag;
3408 skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,3426 skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,
3409 le16_to_cpu(req.size) + sizeof(req),3427 le16_to_cpu(req.size) + sizeof(req),
@@ -3727,7 +3745,7 @@ mt7925_mcu_rate_txpower_band(struct mt76_phy *phy, · 317 unmodified lines
3727 memcpy(tx_power_tlv->alpha2, dev->alpha2, sizeof(dev->alpha2));3745 memcpy(tx_power_tlv->alpha2, dev->alpha2, sizeof(dev->alpha2));
3728 tx_power_tlv->n_chan = num_ch;3746 tx_power_tlv->n_chan = num_ch;
3729 tx_power_tlv->tag = cpu_to_le16(0x1);3747 tx_power_tlv->tag = cpu_to_le16(0x1);
3730 tx_power_tlv->len = cpu_to_le16(sizeof(*tx_power_tlv));3748 tx_power_tlv->len = cpu_to_le16(msg_len);
3731 3749
3732 switch (band) {3750 switch (band) {
3733 case NL80211_BAND_2GHZ:3751 case NL80211_BAND_2GHZ:
drivers/net/wireless/mediatek/mt76/mt7925/mcu.h+7−0
@@ -693,6 +693,13 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy, · 692 unmodified lines
693 struct ieee80211_bss_conf *link_conf,693 struct ieee80211_bss_conf *link_conf,
694 struct ieee80211_link_sta *link_sta,694 struct ieee80211_link_sta *link_sta,
695 int enable);695 int enable);
696int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
697 struct ieee80211_chanctx_conf *ctx,
698 struct ieee80211_bss_conf *link_conf,
699 struct ieee80211_link_sta *link_sta,
700 u16 bmc_tx_wlan_idx,
701 u16 sta_wlan_idx,
702 int enable);
696int mt7925_mcu_set_timing(struct mt792x_phy *phy,703int mt7925_mcu_set_timing(struct mt792x_phy *phy,
697 struct ieee80211_bss_conf *link_conf);704 struct ieee80211_bss_conf *link_conf);
698int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);705int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);
drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h+8−5
@@ -250,7 +250,9 @@ int mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, · 249 unmodified lines
250 bool enable);250 bool enable);
251int mt7925_mcu_sta_update(struct mt792x_dev *dev,251int mt7925_mcu_sta_update(struct mt792x_dev *dev,
252 struct ieee80211_link_sta *link_sta,252 struct ieee80211_link_sta *link_sta,
253 struct ieee80211_vif *vif, bool enable,253 struct ieee80211_vif *vif,
254 struct mt792x_link_sta *mlink,
255 bool enable,
254 enum mt76_sta_info_state state);256 enum mt76_sta_info_state state);
255int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag);257int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag);
256int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_bss_conf *bss_conf);258int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_bss_conf *bss_conf);
@@ -298,6 +300,7 @@ int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev, · 41 unmodified lines
298void mt7925_mlo_pm_work(struct work_struct *work);300void mt7925_mlo_pm_work(struct work_struct *work);
299void mt7925_scan_work(struct work_struct *work);301void mt7925_scan_work(struct work_struct *work);
300void mt7925_roc_work(struct work_struct *work);302void mt7925_roc_work(struct work_struct *work);
303void mt7925_csa_work(struct work_struct *work);
301int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev,304int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev,
302 struct ieee80211_bss_conf *link_conf);305 struct ieee80211_bss_conf *link_conf);
303void mt7925_coredump_work(struct work_struct *work);306void mt7925_coredump_work(struct work_struct *work);
@@ -349,8 +352,8 @@ int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw, · 45 unmodified lines
349int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set);352int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set);
350int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,353int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
351 enum environment_cap env_cap);354 enum environment_cap env_cap);
352int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,355int mt7925_mcu_set_mlo_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
353 int duration, u8 token_id);356 u16 sel_links, int duration, u8 token_id);
354int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,357int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
355 struct ieee80211_channel *chan, int duration,358 struct ieee80211_channel *chan, int duration,
356 enum mt7925_roc_req type, u8 token_id);359 enum mt7925_roc_req type, u8 token_id);
@@ -367,8 +370,8 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, · 10 unmodified lines
367int mt7925_mcu_set_rts_thresh(struct mt792x_phy *phy, u32 val);370int mt7925_mcu_set_rts_thresh(struct mt792x_phy *phy, u32 val);
368int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,371int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
369 struct ieee80211_vif *vif,372 struct ieee80211_vif *vif,
370 struct ieee80211_sta *sta,373 struct mt792x_bss_conf *mconf,
371 int link_id);374 struct mt792x_link_sta *mlink);
372int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy);375int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy);
373 376
374int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,377int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
drivers/net/wireless/mediatek/mt76/mt7925/regd.c+2−1
@@ -232,7 +232,8 @@ int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2) · 231 unmodified lines
232 dev->regd_user)232 dev->regd_user)
233 return -EINVAL;233 return -EINVAL;
234 234
235 if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')235 if ((mdev->alpha2[0] && mdev->alpha2[0] != '0') &&
236 (mdev->alpha2[1] && mdev->alpha2[1] != '0'))
236 return 0;237 return 0;
237 238
238 /* do not need to update the same country twice */239 /* do not need to update the same country twice */
drivers/net/wireless/mediatek/mt76/mt792x.h+7−0
@@ -41,11 +41,13 @@ · 40 unmodified lines
41#define MT792x_MCU_INIT_RETRY_COUNT 1041#define MT792x_MCU_INIT_RETRY_COUNT 10
42#define MT792x_WFSYS_INIT_RETRY_COUNT 242#define MT792x_WFSYS_INIT_RETRY_COUNT 2
43 43
44#define MT7902_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7902_1.bin"
44#define MT7920_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1a.bin"45#define MT7920_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1a.bin"
45#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"46#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
46#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"47#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
47#define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"48#define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"
48 49
50#define MT7902_ROM_PATCH "mediatek/WIFI_MT7902_patch_mcu_1_1_hdr.bin"
49#define MT7920_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.bin"51#define MT7920_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.bin"
50#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"52#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
51#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"53#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
@@ -95,6 +97,7 @@ DECLARE_EWMA(avg_signal, 10, 8) · 43 unmodified lines
95 97
96struct mt792x_link_sta {98struct mt792x_link_sta {
97 struct mt76_wcid wcid; /* must be first */99 struct mt76_wcid wcid; /* must be first */
100 struct rcu_head rcu_head;
98 101
99 u32 airtime_ac[8];102 u32 airtime_ac[8];
100 103
@@ -448,6 +451,8 @@ void mt792x_config_mac_addr_list(struct mt792x_dev *dev); · 347 unmodified lines
448static inline char *mt792x_ram_name(struct mt792x_dev *dev)451static inline char *mt792x_ram_name(struct mt792x_dev *dev)
449{452{
450 switch (mt76_chip(&dev->mt76)) {453 switch (mt76_chip(&dev->mt76)) {
454 case 0x7902:
455 return MT7902_FIRMWARE_WM;
451 case 0x7920:456 case 0x7920:
452 return MT7920_FIRMWARE_WM;457 return MT7920_FIRMWARE_WM;
453 case 0x7922:458 case 0x7922:
@@ -462,6 +467,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev) · 8 unmodified lines
462static inline char *mt792x_patch_name(struct mt792x_dev *dev)467static inline char *mt792x_patch_name(struct mt792x_dev *dev)
463{468{
464 switch (mt76_chip(&dev->mt76)) {469 switch (mt76_chip(&dev->mt76)) {
470 case 0x7902:
471 return MT7902_ROM_PATCH;
465 case 0x7920:472 case 0x7920:
466 return MT7920_ROM_PATCH;473 return MT7920_ROM_PATCH;
467 case 0x7922:474 case 0x7922:
drivers/net/wireless/mediatek/mt76/mt792x_core.c+10−4
@@ -151,7 +151,7 @@ void mt792x_stop(struct ieee80211_hw *hw, bool suspend) · 150 unmodified lines
151 cancel_work_sync(&dev->reset_work);151 cancel_work_sync(&dev->reset_work);
152 mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);152 mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
153 153
154 if (is_mt7921(&dev->mt76)) {154 if (is_connac2(&dev->mt76)) {
155 mt792x_mutex_acquire(dev);155 mt792x_mutex_acquire(dev);
156 mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);156 mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
157 mt792x_mutex_release(dev);157 mt792x_mutex_release(dev);
@@ -691,9 +691,8 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw) · 533 unmodified lines
691 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);691 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
692 ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);692 ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
693 693
694 if (is_mt7921(&dev->mt76)) {694 ieee80211_hw_set(hw, CHANCTX_STA_CSA);
695 ieee80211_hw_set(hw, CHANCTX_STA_CSA);695
696 }
697 696
698 if (dev->pm.enable)697 if (dev->pm.enable)
699 ieee80211_hw_set(hw, CONNECTION_MONITOR);698 ieee80211_hw_set(hw, CONNECTION_MONITOR);
@@ -927,6 +926,13 @@ int mt792x_load_firmware(struct mt792x_dev *dev) · 227 unmodified lines
927{926{
928 int ret;927 int ret;
929 928
929 mt76_connac_mcu_restart(&dev->mt76);
930
931 if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC_FW_STATE,
932 MT_TOP_MISC2_FW_PWR_ON, 1000))
933 dev_warn(dev->mt76.dev,
934 "MCU is not ready for firmware download\n");
935
930 ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev));936 ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev));
931 if (ret)937 if (ret)
932 return ret;938 return ret;
drivers/net/wireless/mediatek/mt76/mt792x_dma.c+17−1
@@ -103,6 +103,22 @@ static void mt792x_dma_prefetch(struct mt792x_dev *dev) · 102 unmodified lines
103 mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10));103 mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10));
104 mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4));104 mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4));
105 mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0540, 0x4));105 mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0540, 0x4));
106 } else if (is_mt7902(&dev->mt76)) {
107 /* rx ring */
108 mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x4));
109 mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x0040, 0x4));
110 mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x0080, 0x4));
111 mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x00c0, 0x4));
112 /* tx ring */
113 mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0100, 0x4));
114 mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x0140, 0x4));
115 mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x0180, 0x4));
116 mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x01c0, 0x4));
117 mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x0200, 0x4));
118 mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x0240, 0x4));
119 mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x0280, 0x4));
120 mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x02c0, 0x4));
121 mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0300, 0x4));
106 } else {122 } else {
107 /* rx ring */123 /* rx ring */
108 mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));124 mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
@@ -356,7 +372,7 @@ EXPORT_SYMBOL_GPL(mt792x_poll_rx); · 247 unmodified lines
356 372
357int mt792x_wfsys_reset(struct mt792x_dev *dev)373int mt792x_wfsys_reset(struct mt792x_dev *dev)
358{374{
359 u32 addr = is_mt7921(&dev->mt76) ? 0x18000140 : 0x7c000140;375 u32 addr = is_connac2(&dev->mt76) ? 0x18000140 : 0x7c000140;
360 376
361 mt76_clear(dev, addr, WFSYS_SW_RST_B);377 mt76_clear(dev, addr, WFSYS_SW_RST_B);
362 msleep(50);378 msleep(50);
drivers/net/wireless/mediatek/mt76/mt792x_mac.c+1−1
@@ -375,7 +375,7 @@ void mt792x_pm_power_save_work(struct work_struct *work) · 374 unmodified lines
375 }375 }
376 376
377 if (!mt792x_mcu_fw_pmctrl(dev)) {377 if (!mt792x_mcu_fw_pmctrl(dev)) {
378 cancel_delayed_work_sync(&mphy->mac_work);378 cancel_delayed_work(&mphy->mac_work);
379 return;379 return;
380 }380 }
381out:381out:
drivers/net/wireless/mediatek/mt76/mt792x_regs.h+6−0
@@ -25,6 +25,8 @@ · 24 unmodified lines
25#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))25#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))
26#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))26#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
27 27
28#define MT_PSE_BASE 0x820c8000
29
28/* TMAC: band 0(0x21000), band 1(0xa1000) */30/* TMAC: band 0(0x21000), band 1(0xa1000) */
29#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000)31#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000)
30#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))32#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
@@ -390,6 +392,10 @@ · 359 unmodified lines
390#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600)392#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600)
391#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)393#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)
392 394
395#define MT7925_CBTOP_RGU_WF_SUBSYS_RST 0x70028600
396#define MT7925_WFSYS_INIT_DONE_ADDR 0x184c1604
397#define MT7925_WFSYS_INIT_DONE 0x00001d1e
398
393#define MT_HW_BOUND 0x70010020399#define MT_HW_BOUND 0x70010020
394#define MT_HW_CHIPID 0x70010200400#define MT_HW_CHIPID 0x70010200
395#define MT_HW_REV 0x70010204401#define MT_HW_REV 0x70010204
drivers/net/wireless/mediatek/mt76/mt792x_usb.c+43−8
@@ -206,6 +206,33 @@ static void mt792xu_epctl_rst_opt(struct mt792x_dev *dev, bool reset) · 205 unmodified lines
206 mt792xu_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);206 mt792xu_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
207}207}
208 208
209struct mt792xu_wfsys_desc {
210 u32 rst_reg;
211 u32 done_reg;
212 u32 done_mask;
213 u32 done_val;
214 u32 delay_ms;
215 bool need_status_sel;
216};
217
218static const struct mt792xu_wfsys_desc mt7921_wfsys_desc = {
219 .rst_reg = MT_CBTOP_RGU_WF_SUBSYS_RST,
220 .done_reg = MT_UDMA_CONN_INFRA_STATUS,
221 .done_mask = MT_UDMA_CONN_WFSYS_INIT_DONE,
222 .done_val = MT_UDMA_CONN_WFSYS_INIT_DONE,
223 .delay_ms = 0,
224 .need_status_sel = true,
225};
226
227static const struct mt792xu_wfsys_desc mt7925_wfsys_desc = {
228 .rst_reg = MT7925_CBTOP_RGU_WF_SUBSYS_RST,
229 .done_reg = MT7925_WFSYS_INIT_DONE_ADDR,
230 .done_mask = U32_MAX,
231 .done_val = MT7925_WFSYS_INIT_DONE,
232 .delay_ms = 20,
233 .need_status_sel = false,
234};
235
209int mt792xu_dma_init(struct mt792x_dev *dev, bool resume)236int mt792xu_dma_init(struct mt792x_dev *dev, bool resume)
210{237{
211 int err;238 int err;
@@ -236,25 +263,33 @@ EXPORT_SYMBOL_GPL(mt792xu_dma_init); · 24 unmodified lines
236 263
237int mt792xu_wfsys_reset(struct mt792x_dev *dev)264int mt792xu_wfsys_reset(struct mt792x_dev *dev)
238{265{
266 const struct mt792xu_wfsys_desc *desc = is_mt7925(&dev->mt76) ?
267 &mt7925_wfsys_desc :
268 &mt7921_wfsys_desc;
239 u32 val;269 u32 val;
240 int i;270 int i;
241 271
242 mt792xu_epctl_rst_opt(dev, false);272 mt792xu_epctl_rst_opt(dev, false);
243 273
244 val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);274 val = mt792xu_uhw_rr(&dev->mt76, desc->rst_reg);
245 val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;275 val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
246 mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);276 mt792xu_uhw_wr(&dev->mt76, desc->rst_reg, val);
247 277
248 usleep_range(10, 20);278 if (desc->delay_ms)
279 msleep(desc->delay_ms);
280 else
281 usleep_range(10, 20);
249 282
250 val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);283 val = mt792xu_uhw_rr(&dev->mt76, desc->rst_reg);
251 val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;284 val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
252 mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);285 mt792xu_uhw_wr(&dev->mt76, desc->rst_reg, val);
286
287 if (desc->need_status_sel)
288 mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
253 289
254 mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
255 for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) {290 for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) {
256 val = mt792xu_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);291 val = mt792xu_uhw_rr(&dev->mt76, desc->done_reg);
257 if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)292 if ((val & desc->done_mask) == desc->done_val)
258 break;293 break;
259 294
260 msleep(100);295 msleep(100);
drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c+30−6
@@ -226,14 +226,23 @@ mt7996_radar_trigger(void *data, u64 val) · 225 unmodified lines
226#define RADAR_BACKGROUND 2226#define RADAR_BACKGROUND 2
227 struct mt7996_dev *dev = data;227 struct mt7996_dev *dev = data;
228 struct mt7996_phy *phy = mt7996_band_phy(dev, NL80211_BAND_5GHZ);228 struct mt7996_phy *phy = mt7996_band_phy(dev, NL80211_BAND_5GHZ);
229 int rdd_idx;229 struct cfg80211_chan_def *chandef;
230 int rdd_idx, ret;
230 231
231 if (!phy || !val || val > RADAR_BACKGROUND)232 if (!phy || !val || val > RADAR_BACKGROUND)
232 return -EINVAL;233 return -EINVAL;
233 234
234 if (val == RADAR_BACKGROUND && !dev->rdd2_phy) {235 if (test_bit(MT76_SCANNING, &phy->mt76->state))
235 dev_err(dev->mt76.dev, "Background radar is not enabled\n");236 return -EBUSY;
236 return -EINVAL;237
238 if (val == RADAR_BACKGROUND) {
239 if (!dev->rdd2_phy || !cfg80211_chandef_valid(&dev->rdd2_chandef)) {
240 dev_err(dev->mt76.dev, "Background radar is not enabled\n");
241 return -EINVAL;
242 }
243 chandef = &dev->rdd2_chandef;
244 } else {
245 chandef = &phy->mt76->chandef;
237 }246 }
238 247
239 rdd_idx = mt7996_get_rdd_idx(phy, val == RADAR_BACKGROUND);248 rdd_idx = mt7996_get_rdd_idx(phy, val == RADAR_BACKGROUND);
@@ -242,6 +251,11 @@ mt7996_radar_trigger(void *data, u64 val) · 2 unmodified lines
242 return -EINVAL;251 return -EINVAL;
243 }252 }
244 253
254 ret = cfg80211_chandef_dfs_required(dev->mt76.hw->wiphy, chandef,
255 NL80211_IFTYPE_AP);
256 if (ret <= 0)
257 return ret;
258
245 return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, rdd_idx, 0);259 return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, rdd_idx, 0);
246}260}
247 261
@@ -626,13 +640,18 @@ mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta) · 378 unmodified lines
626{640{
627 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;641 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
628 struct mt7996_vif *mvif = msta->vif;642 struct mt7996_vif *mvif = msta->vif;
629 struct mt7996_dev *dev = mvif->deflink.phy->dev;643 struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
630 struct ieee80211_link_sta *link_sta;644 struct ieee80211_link_sta *link_sta;
631 struct seq_file *s = data;645 struct seq_file *s = data;
632 struct ieee80211_vif *vif;646 struct ieee80211_vif *vif;
647 struct mt7996_dev *dev;
633 unsigned int link_id;648 unsigned int link_id;
634 649
650 if (!phy)
651 return;
652
635 vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);653 vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
654 dev = phy->dev;
636 655
637 rcu_read_lock();656 rcu_read_lock();
638 657
@@ -979,13 +998,17 @@ static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file, · 340 unmodified lines
979#define LONG_PREAMBLE 1998#define LONG_PREAMBLE 1
980 struct ieee80211_link_sta *link_sta = file->private_data;999 struct ieee80211_link_sta *link_sta = file->private_data;
981 struct mt7996_sta *msta = (struct mt7996_sta *)link_sta->sta->drv_priv;1000 struct mt7996_sta *msta = (struct mt7996_sta *)link_sta->sta->drv_priv;
982 struct mt7996_dev *dev = msta->vif->deflink.phy->dev;1001 struct mt7996_phy *link_phy = mt7996_vif_link_phy(&msta->vif->deflink);
983 struct mt7996_sta_link *msta_link;1002 struct mt7996_sta_link *msta_link;
984 struct ra_rate phy = {};1003 struct ra_rate phy = {};
1004 struct mt7996_dev *dev;
985 char buf[100];1005 char buf[100];
986 int ret;1006 int ret;
987 u16 gi, ltf;1007 u16 gi, ltf;
988 1008
1009 if (!link_phy)
1010 return -EINVAL;
1011
989 if (count >= sizeof(buf))1012 if (count >= sizeof(buf))
990 return -EINVAL;1013 return -EINVAL;
991 1014
@@ -1008,6 +1031,7 @@ static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file, · 16 unmodified lines
1008 * spe - off: 0, on: 11031 * spe - off: 0, on: 1
1009 * ltf - 1xltf: 0, 2xltf: 1, 4xltf: 21032 * ltf - 1xltf: 0, 2xltf: 1, 4xltf: 2
1010 */1033 */
1034 dev = link_phy->dev;
1011 if (sscanf(buf, "%hhu %hhu %hhu %hhu %hu %hhu %hhu %hhu %hhu %hu",1035 if (sscanf(buf, "%hhu %hhu %hhu %hhu %hu %hhu %hhu %hhu %hhu %hu",
1012 &phy.mode, &phy.bw, &phy.mcs, &phy.nss, &gi,1036 &phy.mode, &phy.bw, &phy.mcs, &phy.nss, &gi,
1013 &phy.preamble, &phy.stbc, &phy.ldpc, &phy.spe, &ltf) != 10) {1037 &phy.preamble, &phy.stbc, &phy.ldpc, &phy.spe, &ltf) != 10) {
drivers/net/wireless/mediatek/mt76/mt7996/dma.c+128−76
@@ -128,15 +128,27 @@ static void mt7996_dma_config(struct mt7996_dev *dev) · 127 unmodified lines
128 128
129 /* data tx queue */129 /* data tx queue */
130 if (is_mt7996(&dev->mt76)) {130 if (is_mt7996(&dev->mt76)) {
131 TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
132 if (dev->hif2) {131 if (dev->hif2) {
133 /* default bn1:ring19 bn2:ring21 */132 if (mt76_npu_device_active(&dev->mt76)) {
134 TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1,133 TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND2,
135 MT7996_TXQ_BAND1);134 MT7996_TXQ_BAND2);
136 TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2,135 TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND0,
137 MT7996_TXQ_BAND2);136 MT7996_TXQ_BAND0);
137 TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND1,
138 MT7996_TXQ_BAND1);
139 } else {
140 /* default bn1:ring19 bn2:ring21 */
141 TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0,
142 MT7996_TXQ_BAND0);
143 TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1,
144 MT7996_TXQ_BAND1);
145 TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2,
146 MT7996_TXQ_BAND2);
147 }
138 } else {148 } else {
139 /* single pcie bn0/1:ring18 bn2:ring19 */149 /* single pcie bn0/1:ring18 bn2:ring19 */
150 TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0,
151 MT7996_TXQ_BAND0);
140 TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND1,152 TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND1,
141 MT7996_TXQ_BAND1);153 MT7996_TXQ_BAND1);
142 }154 }
@@ -350,6 +362,9 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) · 207 unmodified lines
350 if (!mt7996_has_wa(dev) || mt76_npu_device_active(&dev->mt76))362 if (!mt7996_has_wa(dev) || mt76_npu_device_active(&dev->mt76))
351 irq_mask &= ~(MT_INT_RX(MT_RXQ_MAIN_WA) |363 irq_mask &= ~(MT_INT_RX(MT_RXQ_MAIN_WA) |
352 MT_INT_RX(MT_RXQ_BAND1_WA));364 MT_INT_RX(MT_RXQ_BAND1_WA));
365 if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76))
366 irq_mask &= ~(MT_INT_RX(MT_RXQ_TXFREE_BAND0) |
367 MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2));
353 irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;368 irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
354 369
355 mt7996_irq_enable(dev, irq_mask);370 mt7996_irq_enable(dev, irq_mask);
@@ -430,39 +445,48 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) · 74 unmodified lines
430 MT_WFDMA_HOST_CONFIG_BAND1_PCIE1 |445 MT_WFDMA_HOST_CONFIG_BAND1_PCIE1 |
431 MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);446 MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
432 447
433 if (is_mt7996(&dev->mt76))448 if (is_mt7996(&dev->mt76)) {
434 mt76_set(dev, MT_WFDMA_HOST_CONFIG,449 if (mt76_npu_device_active(&dev->mt76))
435 MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);450 mt76_set(dev, MT_WFDMA_HOST_CONFIG,
436 else451 MT_WFDMA_HOST_CONFIG_BAND0_PCIE1);
452 else
453 mt76_set(dev, MT_WFDMA_HOST_CONFIG,
454 MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
455 } else {
437 mt76_set(dev, MT_WFDMA_HOST_CONFIG,456 mt76_set(dev, MT_WFDMA_HOST_CONFIG,
438 MT_WFDMA_HOST_CONFIG_BAND1_PCIE1);457 MT_WFDMA_HOST_CONFIG_BAND1_PCIE1);
458 }
439 459
440 /* AXI read outstanding number */460 /* AXI read outstanding number */
441 mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL,461 mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL,
442 MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK, 0x14);462 MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK, 0x14);
443 463
444 if (dev->hif2->speed < PCIE_SPEED_5_0GT ||464 if (!is_mt7996(&dev->mt76) ||
445 (dev->hif2->speed == PCIE_SPEED_5_0GT &&465 !mt76_npu_device_active(&dev->mt76)) {
446 dev->hif2->width < PCIE_LNK_X2)) {466 if (dev->hif2->speed < PCIE_SPEED_5_0GT ||
447 mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,467 (dev->hif2->speed == PCIE_SPEED_5_0GT &&
448 WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,468 dev->hif2->width < PCIE_LNK_X2)) {
449 FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,469 mt76_rmw(dev,
450 0x1));470 WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
451 mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,471 WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
452 MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,472 FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
453 FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,473 0x1));
454 0x1));474 mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
455 } else if (dev->hif2->speed < PCIE_SPEED_8_0GT ||475 MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
456 (dev->hif2->speed == PCIE_SPEED_8_0GT &&476 FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
457 dev->hif2->width < PCIE_LNK_X2)) {477 0x1));
458 mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,478 } else if (dev->hif2->speed < PCIE_SPEED_8_0GT ||
459 WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,479 (dev->hif2->speed == PCIE_SPEED_8_0GT &&
460 FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,480 dev->hif2->width < PCIE_LNK_X2)) {
461 0x2));481 mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
462 mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,482 WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
463 MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,483 FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
464 FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,484 0x2));
465 0x2));485 mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
486 MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
487 FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
488 0x2));
489 }
466 }490 }
467 491
468 /* WFDMA rx threshold */492 /* WFDMA rx threshold */
@@ -497,7 +521,7 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) · 28 unmodified lines
497int mt7996_dma_rro_init(struct mt7996_dev *dev)521int mt7996_dma_rro_init(struct mt7996_dev *dev)
498{522{
499 struct mt76_dev *mdev = &dev->mt76;523 struct mt76_dev *mdev = &dev->mt76;
500 u32 irq_mask;524 u32 size;
501 int ret;525 int ret;
502 526
503 if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {527 if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
@@ -524,7 +548,8 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev) · 20 unmodified lines
524 mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C],548 mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C],
525 true);549 true);
526 }550 }
527 goto start_hw_rro;551
552 return 0;
528 }553 }
529 554
530 /* ind cmd */555 /* ind cmd */
@@ -545,10 +570,12 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev) · 14 unmodified lines
545 if (mtk_wed_device_active(&mdev->mmio.wed) &&570 if (mtk_wed_device_active(&mdev->mmio.wed) &&
546 mtk_wed_get_rx_capa(&mdev->mmio.wed))571 mtk_wed_get_rx_capa(&mdev->mmio.wed))
547 mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].wed = &mdev->mmio.wed;572 mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].wed = &mdev->mmio.wed;
573
574 size = is_mt7996(mdev) && mt76_npu_device_active(mdev)
575 ? MT7996_NPU_RX_RING_SIZE / 4 : MT7996_RX_RING_SIZE;
548 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0],576 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0],
549 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),577 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),
550 MT7996_RX_RING_SIZE,578 size, MT7996_RX_MSDU_PAGE_SIZE,
551 MT7996_RX_MSDU_PAGE_SIZE,
552 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));579 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));
553 if (ret)580 if (ret)
554 return ret;581 return ret;
@@ -560,10 +587,12 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev) · 5 unmodified lines
560 if (mtk_wed_device_active(&mdev->mmio.wed) &&587 if (mtk_wed_device_active(&mdev->mmio.wed) &&
561 mtk_wed_get_rx_capa(&mdev->mmio.wed))588 mtk_wed_get_rx_capa(&mdev->mmio.wed))
562 mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].wed = &mdev->mmio.wed;589 mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].wed = &mdev->mmio.wed;
590
591 size = is_mt7996(mdev) && mt76_npu_device_active(mdev)
592 ? MT7996_NPU_RX_RING_SIZE / 2 : MT7996_RX_RING_SIZE;
563 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1],593 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1],
564 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),594 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),
565 MT7996_RX_RING_SIZE,595 size, MT7996_RX_MSDU_PAGE_SIZE,
566 MT7996_RX_MSDU_PAGE_SIZE,
567 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));596 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));
568 if (ret)597 if (ret)
569 return ret;598 return ret;
@@ -576,52 +605,60 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev) · 6 unmodified lines
576 if (mtk_wed_device_active(&mdev->mmio.wed) &&605 if (mtk_wed_device_active(&mdev->mmio.wed) &&
577 mtk_wed_get_rx_capa(&mdev->mmio.wed))606 mtk_wed_get_rx_capa(&mdev->mmio.wed))
578 mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].wed = &mdev->mmio.wed;607 mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].wed = &mdev->mmio.wed;
608
609 size = is_mt7996(mdev) && mt76_npu_device_active(mdev)
610 ? MT7996_NPU_RX_RING_SIZE : MT7996_RX_RING_SIZE;
579 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2],611 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2],
580 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),612 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),
581 MT7996_RX_RING_SIZE,613 size, MT7996_RX_MSDU_PAGE_SIZE,
582 MT7996_RX_MSDU_PAGE_SIZE,
583 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));614 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));
584 if (ret)615 if (ret)
585 return ret;616 return ret;
586 }617 }
587 618
588start_hw_rro:619 return 0;
589 if (mtk_wed_device_active(&mdev->mmio.wed)) {620}
590 irq_mask = mdev->mmio.irqmask |621
622void mt7996_dma_rro_start(struct mt7996_dev *dev)
623{
624 u32 irq_mask;
625
626 if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
627 irq_mask = dev->mt76.mmio.irqmask |
591 MT_INT_TX_DONE_BAND2;628 MT_INT_TX_DONE_BAND2;
592 629
593 mt76_wr(dev, MT_INT_MASK_CSR, irq_mask);630 mt76_wr(dev, MT_INT_MASK_CSR, irq_mask);
594 mtk_wed_device_start_hw_rro(&mdev->mmio.wed, irq_mask, false);631 mtk_wed_device_start_hw_rro(&dev->mt76.mmio.wed, irq_mask,
632 false);
595 mt7996_irq_enable(dev, irq_mask);633 mt7996_irq_enable(dev, irq_mask);
596 } else {634 return;
597 if (is_mt7996(&dev->mt76)) {635 }
598 mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND1,
599 mt76_dma_rx_poll);
600 mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND2,
601 mt76_dma_rx_poll);
602 mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND2,
603 mt76_dma_rx_poll);
604 } else {
605 mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND1,
606 mt76_dma_rx_poll);
607 }
608 636
609 mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND0, mt76_dma_rx_poll);637 if (is_mt7996(&dev->mt76)) {
610 if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {638 mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND1,
611 mt76_queue_rx_init(dev, MT_RXQ_RRO_RXDMAD_C,639 mt76_dma_rx_poll);
612 mt76_dma_rx_poll);640 mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND2,
613 } else {641 mt76_dma_rx_poll);
614 mt76_queue_rx_init(dev, MT_RXQ_RRO_IND,642 mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND2,
615 mt76_dma_rx_poll);643 mt76_dma_rx_poll);
616 mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND0,644 } else {
617 mt76_dma_rx_poll);645 mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND1,
618 }646 mt76_dma_rx_poll);
647 }
619 648
620 if (!mt76_npu_device_active(&dev->mt76))649 mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND0, mt76_dma_rx_poll);
621 mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE);650 if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
651 mt76_queue_rx_init(dev, MT_RXQ_RRO_RXDMAD_C,
652 mt76_dma_rx_poll);
653 } else {
654 mt76_queue_rx_init(dev, MT_RXQ_RRO_IND,
655 mt76_dma_rx_poll);
656 mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND0,
657 mt76_dma_rx_poll);
622 }658 }
623 659
624 return 0;660 if (!mt76_npu_device_active(&dev->mt76))
661 mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE);
625}662}
626 663
627int mt7996_dma_init(struct mt7996_dev *dev)664int mt7996_dma_init(struct mt7996_dev *dev)
@@ -642,11 +679,16 @@ int mt7996_dma_init(struct mt7996_dev *dev) · 14 unmodified lines
642 mt7996_dma_disable(dev, true);679 mt7996_dma_disable(dev, true);
643 680
644 /* init tx queue */681 /* init tx queue */
645 ret = mt7996_init_tx_queues(&dev->phy,682 if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76))
646 MT_TXQ_ID(dev->mphy.band_idx),683 ret = mt7996_init_tx_queues(&dev->phy, MT_TXQ_ID(0),
647 MT7996_TX_RING_SIZE,684 MT7996_NPU_TX_RING_SIZE,
648 MT_TXQ_RING_BASE(0),685 MT_TXQ_RING_BASE(0) + hif1_ofs,
649 wed);686 NULL);
687 else
688 ret = mt7996_init_tx_queues(&dev->phy,
689 MT_TXQ_ID(dev->mphy.band_idx),
690 MT7996_TX_RING_SIZE,
691 MT_TXQ_RING_BASE(0), wed);
650 if (ret)692 if (ret)
651 return ret;693 return ret;
652 694
@@ -714,6 +756,9 @@ int mt7996_dma_init(struct mt7996_dev *dev) · 61 unmodified lines
714 (is_mt7992(&dev->mt76)))) {756 (is_mt7992(&dev->mt76)))) {
715 dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;757 dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
716 dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed;758 dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed;
759 } else if (is_mt7992(&dev->mt76) &&
760 mt76_npu_device_active(&dev->mt76)) {
761 dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_NPU_Q_TXFREE(0);
717 }762 }
718 763
719 if (mt7996_has_wa(dev)) {764 if (mt7996_has_wa(dev)) {
@@ -846,6 +891,8 @@ int mt7996_dma_init(struct mt7996_dev *dev) · 126 unmodified lines
846 /* tx free notify event from WA for band0 */891 /* tx free notify event from WA for band0 */
847 dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;892 dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
848 dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed;893 dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed;
894 } else if (mt76_npu_device_active(&dev->mt76)) {
895 dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_NPU_Q_TXFREE(0);
849 }896 }
850 897
851 ret = mt76_queue_alloc(dev,898 ret = mt76_queue_alloc(dev,
@@ -859,16 +906,21 @@ int mt7996_dma_init(struct mt7996_dev *dev) · 7 unmodified lines
859 }906 }
860 907
861 if (mt7996_band_valid(dev, MT_BAND2)) {908 if (mt7996_band_valid(dev, MT_BAND2)) {
909 u32 size;
910
862 /* rx rro data queue for band2 */911 /* rx rro data queue for band2 */
863 dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags =912 dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags =
864 MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;913 MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;
865 if (mtk_wed_device_active(wed) &&914 if (mtk_wed_device_active(wed) &&
866 mtk_wed_get_rx_capa(wed))915 mtk_wed_get_rx_capa(wed))
867 dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed;916 dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed;
917
918 size = is_mt7996(&dev->mt76) &&
919 mt76_npu_device_active(&dev->mt76)
920 ? MT7996_NPU_RX_RING_SIZE : MT7996_RX_RING_SIZE;
868 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],921 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
869 MT_RXQ_ID(MT_RXQ_RRO_BAND2),922 MT_RXQ_ID(MT_RXQ_RRO_BAND2),
870 MT7996_RX_RING_SIZE,923 size, MT7996_RX_BUF_SIZE,
871 MT7996_RX_BUF_SIZE,
872 MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);924 MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);
873 if (ret)925 if (ret)
874 return ret;926 return ret;
drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c+37−27
@@ -33,6 +33,8 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev) · 32 unmodified lines
33 if (dev->var.fem == MT7996_FEM_INT)33 if (dev->var.fem == MT7996_FEM_INT)
34 return MT7992_EEPROM_DEFAULT_23_INT;34 return MT7992_EEPROM_DEFAULT_23_INT;
35 return MT7992_EEPROM_DEFAULT_23;35 return MT7992_EEPROM_DEFAULT_23;
36 case MT7992_VAR_TYPE_24:
37 return MT7992_EEPROM_DEFAULT_24;
36 case MT7992_VAR_TYPE_44:38 case MT7992_VAR_TYPE_44:
37 default:39 default:
38 if (dev->var.fem == MT7996_FEM_INT)40 if (dev->var.fem == MT7996_FEM_INT)
@@ -153,7 +155,7 @@ mt7996_eeprom_check_or_use_default(struct mt7996_dev *dev, bool use_default) · 114 unmodified lines
153 155
154 dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");156 dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
155 memcpy(eeprom, fw->data, MT7996_EEPROM_SIZE);157 memcpy(eeprom, fw->data, MT7996_EEPROM_SIZE);
156 dev->flash_mode = true;158 dev->eeprom_mode = EEPROM_MODE_DEFAULT_BIN;
157 159
158out:160out:
159 release_firmware(fw);161 release_firmware(fw);
@@ -163,26 +165,31 @@ out: · 3 unmodified lines
163 165
164static int mt7996_eeprom_load(struct mt7996_dev *dev)166static int mt7996_eeprom_load(struct mt7996_dev *dev)
165{167{
168 u32 eeprom_blk_size, block_num;
166 bool use_default = false;169 bool use_default = false;
167 int ret;170 int ret, i;
168 171
169 ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);172 ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
170 if (ret < 0)173 if (ret < 0)
171 return ret;174 return ret;
172 175
173 if (ret && !mt7996_check_eeprom(dev)) {176 if (ret && !mt7996_check_eeprom(dev)) {
174 dev->flash_mode = true;177 dev->eeprom_mode = EEPROM_MODE_FLASH;
175 goto out;178 goto out;
176 }179 }
177 180
178 if (!dev->flash_mode) {181 memset(dev->mt76.eeprom.data, 0, MT7996_EEPROM_SIZE);
179 u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;182 if (mt7996_has_ext_eeprom(dev)) {
180 u32 block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);183 /* external eeprom mode */
184 dev->eeprom_mode = EEPROM_MODE_EXT;
185 eeprom_blk_size = MT7996_EXT_EEPROM_BLOCK_SIZE;
186 } else {
181 u8 free_block_num;187 u8 free_block_num;
182 int i;
183 188
184 memset(dev->mt76.eeprom.data, 0, MT7996_EEPROM_SIZE);189 /* efuse mode */
185 ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num);190 dev->eeprom_mode = EEPROM_MODE_EFUSE;
191 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
192 ret = mt7996_mcu_get_efuse_free_block(dev, &free_block_num);
186 if (ret < 0)193 if (ret < 0)
187 return ret;194 return ret;
188 195
@@ -191,27 +198,29 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev) · 2 unmodified lines
191 use_default = true;198 use_default = true;
192 goto out;199 goto out;
193 }200 }
201 }
202
203 /* check if eeprom data from fw is valid */
204 if (mt7996_mcu_get_eeprom(dev, 0, NULL, eeprom_blk_size,
205 dev->eeprom_mode) ||
206 mt7996_check_eeprom(dev)) {
207 use_default = true;
208 goto out;
209 }
210
211 /* read eeprom data from fw */
212 block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
213 for (i = 1; i < block_num; i++) {
214 u32 len = eeprom_blk_size;
194 215
195 /* check if eeprom data from fw is valid */216 if (i == block_num - 1)
196 if (mt7996_mcu_get_eeprom(dev, 0, NULL, 0) ||217 len = MT7996_EEPROM_SIZE % eeprom_blk_size;
197 mt7996_check_eeprom(dev)) {218 ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size,
219 NULL, len, dev->eeprom_mode);
220 if (ret && ret != -EINVAL) {
198 use_default = true;221 use_default = true;
199 goto out;222 goto out;
200 }223 }
201
202 /* read eeprom data from fw */
203 for (i = 1; i < block_num; i++) {
204 u32 len = eeprom_blk_size;
205
206 if (i == block_num - 1)
207 len = MT7996_EEPROM_SIZE % eeprom_blk_size;
208 ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size,
209 NULL, len);
210 if (ret && ret != -EINVAL) {
211 use_default = true;
212 goto out;
213 }
214 }
215 }224 }
216 225
217out:226out:
@@ -385,7 +394,8 @@ bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev) · 167 unmodified lines
385 return false;394 return false;
386 break;395 break;
387 case MT7992_DEVICE_ID:396 case MT7992_DEVICE_ID:
388 if (dev->var.type == MT7992_VAR_TYPE_23)397 if (dev->var.type == MT7992_VAR_TYPE_23 ||
398 dev->var.type == MT7992_VAR_TYPE_24)
389 return false;399 return false;
390 break;400 break;
391 case MT7990_DEVICE_ID: {401 case MT7990_DEVICE_ID: {
drivers/net/wireless/mediatek/mt76/mt7996/init.c+91−19
@@ -34,6 +34,20 @@ static const struct ieee80211_iface_combination if_comb_global = { · 33 unmodified lines
34 BIT(NL80211_CHAN_WIDTH_40) |34 BIT(NL80211_CHAN_WIDTH_40) |
35 BIT(NL80211_CHAN_WIDTH_80) |35 BIT(NL80211_CHAN_WIDTH_80) |
36 BIT(NL80211_CHAN_WIDTH_160),36 BIT(NL80211_CHAN_WIDTH_160),
37 .beacon_int_min_gcd = 100,
38};
39
40static const struct ieee80211_iface_combination if_comb_global_7992 = {
41 .limits = &if_limits_global,
42 .n_limits = 1,
43 .max_interfaces = 32,
44 .num_different_channels = MT7996_MAX_RADIOS - 1,
45 .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
46 BIT(NL80211_CHAN_WIDTH_20) |
47 BIT(NL80211_CHAN_WIDTH_40) |
48 BIT(NL80211_CHAN_WIDTH_80) |
49 BIT(NL80211_CHAN_WIDTH_160),
50 .beacon_int_min_gcd = 100,
37};51};
38 52
39static const struct ieee80211_iface_limit if_limits[] = {53static const struct ieee80211_iface_limit if_limits[] = {
@@ -85,6 +99,7 @@ static const struct wiphy_iftype_ext_capab iftypes_ext_capa[] = { · 45 unmodified lines
85 .extended_capabilities_mask = if_types_ext_capa_ap,99 .extended_capabilities_mask = if_types_ext_capa_ap,
86 .extended_capabilities_len = sizeof(if_types_ext_capa_ap),100 .extended_capabilities_len = sizeof(if_types_ext_capa_ap),
87 .mld_capa_and_ops =101 .mld_capa_and_ops =
102 FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_FREQ_SEP_TYPE_IND, 1) |
88 FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,103 FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,
89 MT7996_MAX_RADIOS - 1),104 MT7996_MAX_RADIOS - 1),
90 },105 },
@@ -485,7 +500,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) · 394 unmodified lines
485 hw->vif_data_size = sizeof(struct mt7996_vif);500 hw->vif_data_size = sizeof(struct mt7996_vif);
486 hw->chanctx_data_size = sizeof(struct mt76_chanctx);501 hw->chanctx_data_size = sizeof(struct mt76_chanctx);
487 502
488 wiphy->iface_combinations = &if_comb_global;503 wiphy->iface_combinations = is_mt7996(&dev->mt76) ? &if_comb_global :
504 &if_comb_global_7992;
489 wiphy->n_iface_combinations = 1;505 wiphy->n_iface_combinations = 1;
490 506
491 wiphy->radio = dev->radios;507 wiphy->radio = dev->radios;
@@ -521,8 +537,10 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) · 29 unmodified lines
521 ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);537 ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
522 ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);538 ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
523 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);539 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
540 ieee80211_hw_set(hw, CHANCTX_STA_CSA);
524 541
525 hw->max_tx_fragments = 4;542 hw->max_tx_fragments = 4;
543 wiphy->txq_memory_limit = 32 << 20; /* 32 MiB */
526 544
527 /* init led callbacks */545 /* init led callbacks */
528 if (IS_ENABLED(CONFIG_MT76_LEDS)) {546 if (IS_ENABLED(CONFIG_MT76_LEDS)) {
@@ -592,7 +610,7 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev) · 63 unmodified lines
592void mt7996_mac_init(struct mt7996_dev *dev)610void mt7996_mac_init(struct mt7996_dev *dev)
593{611{
594#define HIF_TXD_V2_1 0x21612#define HIF_TXD_V2_1 0x21
595 int i;613 int i, rx_path_type;
596 614
597 mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);615 mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
598 616
@@ -606,11 +624,16 @@ void mt7996_mac_init(struct mt7996_dev *dev) · 7 unmodified lines
606 }624 }
607 625
608 /* rro module init */626 /* rro module init */
609 if (dev->hif2)627 if (dev->hif2) {
628 if (mt76_npu_device_active(&dev->mt76))
629 rx_path_type = is_mt7996(&dev->mt76) ? 6 : 8;
630 else
631 rx_path_type = is_mt7996(&dev->mt76) ? 2 : 7;
610 mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,632 mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,
611 is_mt7996(&dev->mt76) ? 2 : 7);633 rx_path_type);
612 else634 } else {
613 mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 0);635 mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 0);
636 }
614 637
615 if (mt7996_has_hwrro(dev)) {638 if (mt7996_has_hwrro(dev)) {
616 u16 timeout;639 u16 timeout;
@@ -668,8 +691,9 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band) · 51 unmodified lines
668 return 0;691 return 0;
669 692
670 if (dev->hif2 &&693 if (dev->hif2 &&
671 ((is_mt7996(&dev->mt76) && band == MT_BAND2) ||694 ((is_mt7992(&dev->mt76) && band == MT_BAND1) ||
672 (is_mt7992(&dev->mt76) && band == MT_BAND1))) {695 (is_mt7996(&dev->mt76) && band == MT_BAND2 &&
696 !mt76_npu_device_active(&dev->mt76)))) {
673 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);697 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
674 wed = &dev->mt76.mmio.wed_hif2;698 wed = &dev->mt76.mmio.wed_hif2;
675 }699 }
@@ -709,14 +733,19 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band) · 33 unmodified lines
709 /* init wiphy according to mphy and phy */733 /* init wiphy according to mphy and phy */
710 mt7996_init_wiphy_band(mphy->hw, phy);734 mt7996_init_wiphy_band(mphy->hw, phy);
711 735
712 if (is_mt7996(&dev->mt76) && !dev->hif2 && band == MT_BAND1) {736 if (is_mt7996(&dev->mt76) &&
737 ((band == MT_BAND1 && !dev->hif2) ||
738 (band == MT_BAND2 && mt76_npu_device_active(&dev->mt76)))) {
713 int i;739 int i;
714 740
715 for (i = 0; i <= MT_TXQ_PSD; i++)741 for (i = 0; i <= MT_TXQ_PSD; i++)
716 mphy->q_tx[i] = dev->mt76.phys[MT_BAND0]->q_tx[0];742 mphy->q_tx[i] = dev->mt76.phys[band - 1]->q_tx[0];
717 } else {743 } else {
718 ret = mt7996_init_tx_queues(mphy->priv, MT_TXQ_ID(band),744 int size = is_mt7996(&dev->mt76) &&
719 MT7996_TX_RING_SIZE,745 mt76_npu_device_active(&dev->mt76)
746 ? MT7996_NPU_TX_RING_SIZE / 2 : MT7996_TX_RING_SIZE;
747
748 ret = mt7996_init_tx_queues(mphy->priv, MT_TXQ_ID(band), size,
720 MT_TXQ_RING_BASE(band) + hif1_ofs,749 MT_TXQ_RING_BASE(band) + hif1_ofs,
721 wed);750 wed);
722 if (ret)751 if (ret)
@@ -756,15 +785,41 @@ static void mt7996_init_work(struct work_struct *work) · 33 unmodified lines
756 mt7996_mcu_set_eeprom(dev);785 mt7996_mcu_set_eeprom(dev);
757 mt7996_mac_init(dev);786 mt7996_mac_init(dev);
758 mt7996_txbf_init(dev);787 mt7996_txbf_init(dev);
788
789 if (!is_mt7990(&dev->mt76))
790 mt7996_mcu_set_dup_wtbl(dev);
759}791}
760 792
761void mt7996_wfsys_reset(struct mt7996_dev *dev)793void mt7996_wfsys_reset(struct mt7996_dev *dev)
762{794{
763 mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);795 if (!is_mt7990(&dev->mt76)) {
764 msleep(20);796 mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
797 msleep(20);
798
799 mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);
800 msleep(20);
801
802 return;
803 }
804
805 if (!dev->recovery.hw_full_reset)
806 return;
765 807
766 mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);808 mt76_set(dev, MT_WF_SUBSYS_RST,
809 MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT |
810 MT_WF_SUBSYS_RST_BYPASS_WFDMA_SLP_PROT |
811 MT_WF_SUBSYS_RST_BYPASS_WFDMA2_SLP_PROT);
812 mt76_rmw(dev, MT_WF_SUBSYS_RST,
813 MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE,
814 u32_encode_bits(0x20, MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE));
815 mt76_clear(dev, MT_WF_L05_RST, MT_WF_L05_RST_WF_RST_MASK);
816 mt76_set(dev, MT_WF_SUBSYS_RST, MT_WF_SUBSYS_RST_WHOLE_PATH_RST);
767 msleep(20);817 msleep(20);
818
819 if (mt76_poll(dev, MT_WF_L05_RST, MT_WF_L05_RST_WF_RST_MASK, 0x1a, 1000))
820 return;
821
822 dev_err(dev->mt76.dev, "wfsys reset fail\n");
768}823}
769 824
770static void mt7996_rro_hw_init_v3(struct mt7996_dev *dev)825static void mt7996_rro_hw_init_v3(struct mt7996_dev *dev)
@@ -842,8 +897,7 @@ void mt7996_rro_hw_init(struct mt7996_dev *dev) · 71 unmodified lines
842 }897 }
843 } else {898 } else {
844 /* set emul 3.0 function */899 /* set emul 3.0 function */
845 mt76_wr(dev, MT_RRO_3_0_EMU_CONF,900 mt76_set(dev, MT_RRO_3_0_EMU_CONF, MT_RRO_3_0_EMU_CONF_EN_MASK);
846 MT_RRO_3_0_EMU_CONF_EN_MASK);
847 901
848 mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE0,902 mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE0,
849 dev->wed_rro.addr_elem[0].phy_addr);903 dev->wed_rro.addr_elem[0].phy_addr);
@@ -935,6 +989,12 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev) · 85 unmodified lines
935 addr++;989 addr++;
936 }990 }
937 991
992 if (is_mt7996(&dev->mt76) &&
993 mt76_npu_device_active(&dev->mt76))
994 mt76_npu_send_txrx_addr(&dev->mt76, 0, i,
995 dev->wed_rro.addr_elem[i].phy_addr,
996 0, 0);
997
938#ifdef CONFIG_NET_MEDIATEK_SOC_WED998#ifdef CONFIG_NET_MEDIATEK_SOC_WED
939 if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&999 if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
940 mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) {1000 mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) {
@@ -995,6 +1055,10 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev) · 54 unmodified lines
995 addr++;1055 addr++;
996 }1056 }
997 1057
1058 if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76))
1059 mt76_npu_send_txrx_addr(&dev->mt76, 1, 0,
1060 dev->wed_rro.session.phy_addr, 0, 0);
1061
998 mt7996_rro_hw_init(dev);1062 mt7996_rro_hw_init(dev);
999 1063
1000 return mt7996_dma_rro_init(dev);1064 return mt7996_dma_rro_init(dev);
@@ -1081,8 +1145,12 @@ static void mt7996_wed_rro_work(struct work_struct *work) · 80 unmodified lines
1081 list);1145 list);
1082 list_del_init(&e->list);1146 list_del_init(&e->list);
1083 1147
1084 if (mt76_npu_device_active(&dev->mt76))1148 if (mt76_npu_device_active(&dev->mt76)) {
1149 if (is_mt7996(&dev->mt76))
1150 mt76_npu_send_txrx_addr(&dev->mt76, 3, e->id,
1151 0, 0, 0);
1085 goto reset_session;1152 goto reset_session;
1153 }
1086 1154
1087 for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {1155 for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
1088 void *ptr = dev->wed_rro.session.ptr;1156 void *ptr = dev->wed_rro.session.ptr;
@@ -1129,7 +1197,7 @@ static int mt7996_variant_type_init(struct mt7996_dev *dev) · 40 unmodified lines
1129 else if (u32_get_bits(val, MT_PAD_GPIO_ADIE_COMB_7992))1197 else if (u32_get_bits(val, MT_PAD_GPIO_ADIE_COMB_7992))
1130 var_type = MT7992_VAR_TYPE_44;1198 var_type = MT7992_VAR_TYPE_44;
1131 else1199 else
1132 return -EINVAL;1200 var_type = MT7992_VAR_TYPE_24;
1133 break;1201 break;
1134 case MT7990_DEVICE_ID:1202 case MT7990_DEVICE_ID:
1135 var_type = MT7990_VAR_TYPE_23;1203 var_type = MT7990_VAR_TYPE_23;
@@ -1163,7 +1231,8 @@ static int mt7996_variant_fem_init(struct mt7996_dev *dev) · 27 unmodified lines
1163 if (ret)1231 if (ret)
1164 return ret;1232 return ret;
1165 1233
1166 ret = mt7996_mcu_get_eeprom(dev, MT7976C_EFUSE_OFFSET, buf, sizeof(buf));1234 ret = mt7996_mcu_get_eeprom(dev, MT7976C_EFUSE_OFFSET, buf, sizeof(buf),
1235 EEPROM_MODE_EFUSE);
1167 if (ret && ret != -EINVAL)1236 if (ret && ret != -EINVAL)
1168 return ret;1237 return ret;
1169 1238
@@ -1696,6 +1765,8 @@ int mt7996_register_device(struct mt7996_dev *dev) · 526 unmodified lines
1696 if (ret)1765 if (ret)
1697 return ret;1766 return ret;
1698 1767
1768 mt7996_dma_rro_start(dev);
1769
1699 ret = mt76_register_device(&dev->mt76, true, mt76_rates,1770 ret = mt76_register_device(&dev->mt76, true, mt76_rates,
1700 ARRAY_SIZE(mt76_rates));1771 ARRAY_SIZE(mt76_rates));
1701 if (ret)1772 if (ret)
@@ -1726,6 +1797,7 @@ error: · 24 unmodified lines
1726 1797
1727void mt7996_unregister_device(struct mt7996_dev *dev)1798void mt7996_unregister_device(struct mt7996_dev *dev)
1728{1799{
1800 cancel_work_sync(&dev->dump_work);
1729 cancel_work_sync(&dev->wed_rro.work);1801 cancel_work_sync(&dev->wed_rro.work);
1730 mt7996_unregister_phy(mt7996_phy3(dev));1802 mt7996_unregister_phy(mt7996_phy3(dev));
1731 mt7996_unregister_phy(mt7996_phy2(dev));1803 mt7996_unregister_phy(mt7996_phy2(dev));
drivers/net/wireless/mediatek/mt76/mt7996/mac.c+50−111
@@ -13,45 +13,6 @@ · 12 unmodified lines
13 13
14#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)14#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
15 15
16static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
17 .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
18 .radar_pattern = {
19 [5] = { 1, 0, 6, 32, 28, 0, 990, 5010, 17, 1, 1 },
20 [6] = { 1, 0, 9, 32, 28, 0, 615, 5010, 27, 1, 1 },
21 [7] = { 1, 0, 15, 32, 28, 0, 240, 445, 27, 1, 1 },
22 [8] = { 1, 0, 12, 32, 28, 0, 240, 510, 42, 1, 1 },
23 [9] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 12, 32, 28, { }, 126 },
24 [10] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 15, 32, 24, { }, 126 },
25 [11] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 18, 32, 28, { }, 54 },
26 [12] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 27, 32, 24, { }, 54 },
27 },
28};
29
30static const struct mt7996_dfs_radar_spec fcc_radar_specs = {
31 .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
32 .radar_pattern = {
33 [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 },
34 [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 },
35 [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 },
36 [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 },
37 [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 },
38 },
39};
40
41static const struct mt7996_dfs_radar_spec jp_radar_specs = {
42 .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
43 .radar_pattern = {
44 [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 },
45 [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 },
46 [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 },
47 [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 },
48 [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 },
49 [13] = { 1, 0, 7, 32, 28, 0, 3836, 3856, 14, 1, 1 },
50 [14] = { 1, 0, 6, 32, 28, 0, 615, 5010, 110, 1, 1 },
51 [15] = { 1, 1, 0, 0, 0, 0, 15, 5010, 110, 0, 0, 12, 32, 28 },
52 },
53};
54
55static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,16static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
56 u16 idx, u8 band_idx)17 u16 idx, u8 band_idx)
57{18{
@@ -527,7 +488,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, · 469 unmodified lines
527 !(csum_status & (BIT(0) | BIT(2) | BIT(3))))488 !(csum_status & (BIT(0) | BIT(2) | BIT(3))))
528 skb->ip_summed = CHECKSUM_UNNECESSARY;489 skb->ip_summed = CHECKSUM_UNNECESSARY;
529 490
530 if (rxd1 & MT_RXD3_NORMAL_FCS_ERR)491 if (rxd3 & MT_RXD3_NORMAL_FCS_ERR)
531 status->flag |= RX_FLAG_FAILED_FCS_CRC;492 status->flag |= RX_FLAG_FAILED_FCS_CRC;
532 493
533 if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR)494 if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR)
@@ -700,6 +661,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, · 166 unmodified lines
700 661
701 hdr = mt76_skb_get_hdr(skb);662 hdr = mt76_skb_get_hdr(skb);
702 fc = hdr->frame_control;663 fc = hdr->frame_control;
664 if (ieee80211_is_beacon(fc))
665 mt76_rx_beacon(mphy, skb);
703 if (ieee80211_is_data_qos(fc)) {666 if (ieee80211_is_data_qos(fc)) {
704 u8 *qos = ieee80211_get_qos_ctl(hdr);667 u8 *qos = ieee80211_get_qos_ctl(hdr);
705 668
@@ -1139,10 +1102,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 433 unmodified lines
1139 * req1102 * req
1140 */1103 */
1141 if (le32_to_cpu(ptr[7]) & MT_TXD7_MAC_TXD) {1104 if (le32_to_cpu(ptr[7]) & MT_TXD7_MAC_TXD) {
1142 u32 val;1105 u32 val, mac_txp_size = sizeof(struct mt76_connac_hw_txp);
1143 1106
1144 ptr = (__le32 *)(txwi + MT_TXD_SIZE);1107 ptr = (__le32 *)(txwi + MT_TXD_SIZE);
1145 memset((void *)ptr, 0, sizeof(struct mt76_connac_fw_txp));1108 memset((void *)ptr, 0, mac_txp_size);
1146 1109
1147 val = FIELD_PREP(MT_TXP0_TOKEN_ID0, id) |1110 val = FIELD_PREP(MT_TXP0_TOKEN_ID0, id) |
1148 MT_TXP0_TOKEN_ID0_VALID_MASK;1111 MT_TXP0_TOKEN_ID0_VALID_MASK;
@@ -1161,6 +1124,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 12 unmodified lines
1161 tx_info->buf[1].addr >> 32);1124 tx_info->buf[1].addr >> 32);
1162#endif1125#endif
1163 ptr[3] = cpu_to_le32(val);1126 ptr[3] = cpu_to_le32(val);
1127
1128 tx_info->buf[0].len = MT_TXD_SIZE + mac_txp_size;
1164 } else {1129 } else {
1165 struct mt76_connac_txp_common *txp;1130 struct mt76_connac_txp_common *txp;
1166 1131
@@ -1270,8 +1235,9 @@ mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta, · 103 unmodified lines
1270 if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))1235 if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
1271 return;1236 return;
1272 1237
1273 if (!test_and_set_bit(tid, &wcid->ampdu_state))1238 if (!test_and_set_bit(tid, &wcid->ampdu_state) &&
1274 ieee80211_start_tx_ba_session(link_sta->sta, tid, 0);1239 ieee80211_start_tx_ba_session(link_sta->sta, tid, 0))
1240 clear_bit(tid, &wcid->ampdu_state);
1275}1241}
1276 1242
1277static void1243static void
@@ -2203,9 +2169,14 @@ mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) · 925 unmodified lines
2203 2169
2204 for_each_vif_active_link(vif, link_conf, link_id) {2170 for_each_vif_active_link(vif, link_conf, link_id) {
2205 struct mt7996_vif_link *link;2171 struct mt7996_vif_link *link;
2172 struct mt7996_phy *link_phy;
2206 2173
2207 link = mt7996_vif_link(dev, vif, link_id);2174 link = mt7996_vif_link(dev, vif, link_id);
2208 if (!link || link->phy != phy)2175 if (!link)
2176 continue;
2177
2178 link_phy = mt7996_vif_link_phy(link);
2179 if (link_phy != phy)
2209 continue;2180 continue;
2210 2181
2211 mt7996_mcu_add_beacon(dev->mt76.hw, vif, link_conf,2182 mt7996_mcu_add_beacon(dev->mt76.hw, vif, link_conf,
@@ -2248,6 +2219,12 @@ void mt7996_tx_token_put(struct mt7996_dev *dev) · 36 unmodified lines
2248 }2219 }
2249 spin_unlock_bh(&dev->mt76.token_lock);2220 spin_unlock_bh(&dev->mt76.token_lock);
2250 idr_destroy(&dev->mt76.token);2221 idr_destroy(&dev->mt76.token);
2222
2223 for (id = 0; id < __MT_MAX_BAND; id++) {
2224 struct mt76_phy *phy = dev->mt76.phys[id];
2225 if (phy)
2226 atomic_set(&phy->mgmt_tx_pending, 0);
2227 }
2251}2228}
2252 2229
2253static int2230static int
@@ -2395,23 +2372,8 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta) · 141 unmodified lines
2395 struct mt7996_dev *dev = data;2372 struct mt7996_dev *dev = data;
2396 int i;2373 int i;
2397 2374
2398 for (i = 0; i < ARRAY_SIZE(msta->link); i++) {2375 for (i = 0; i < ARRAY_SIZE(msta->link); i++)
2399 struct mt7996_sta_link *msta_link = NULL;2376 mt7996_mac_sta_remove_link(dev, sta, i, true);
2400
2401 msta_link = rcu_replace_pointer(msta->link[i], msta_link,
2402 lockdep_is_held(&dev->mt76.mutex));
2403 if (!msta_link)
2404 continue;
2405
2406 mt7996_mac_sta_deinit_link(dev, msta_link);
2407
2408 if (msta->deflink_id == i) {
2409 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
2410 continue;
2411 }
2412
2413 kfree_rcu(msta_link, rcu_head);
2414 }
2415}2377}
2416 2378
2417static void2379static void
@@ -2544,6 +2506,7 @@ void mt7996_mac_reset_work(struct work_struct *work) · 126 unmodified lines
2544 if (mtk_wed_device_active(&dev->mt76.mmio.wed))2506 if (mtk_wed_device_active(&dev->mt76.mmio.wed))
2545 mtk_wed_device_stop(&dev->mt76.mmio.wed);2507 mtk_wed_device_stop(&dev->mt76.mmio.wed);
2546 2508
2509 mt7996_npu_hw_stop(dev);
2547 ieee80211_stop_queues(mt76_hw(dev));2510 ieee80211_stop_queues(mt76_hw(dev));
2548 2511
2549 set_bit(MT76_RESET, &dev->mphy.state);2512 set_bit(MT76_RESET, &dev->mphy.state);
@@ -2564,14 +2527,19 @@ void mt7996_mac_reset_work(struct work_struct *work) · 14 unmodified lines
2564 mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))2527 mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
2565 continue;2528 continue;
2566 2529
2530 if (mt76_npu_device_active(&dev->mt76) &&
2531 mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
2532 continue;
2533
2534 if (mt76_queue_is_npu_txfree(&dev->mt76.q_rx[i]))
2535 continue;
2536
2567 napi_disable(&dev->mt76.napi[i]);2537 napi_disable(&dev->mt76.napi[i]);
2568 }2538 }
2569 napi_disable(&dev->mt76.tx_napi);2539 napi_disable(&dev->mt76.tx_napi);
2570 2540
2571 mutex_lock(&dev->mt76.mutex);2541 mutex_lock(&dev->mt76.mutex);
2572 2542
2573 mt7996_npu_hw_stop(dev);
2574
2575 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);2543 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
2576 2544
2577 if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {2545 if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
@@ -2591,7 +2559,7 @@ void mt7996_mac_reset_work(struct work_struct *work) · 13 unmodified lines
2591 mt7996_dma_start(dev, false, false);2559 mt7996_dma_start(dev, false, false);
2592 2560
2593 if (!is_mt7996(&dev->mt76) && dev->mt76.hwrro_mode == MT76_HWRRO_V3)2561 if (!is_mt7996(&dev->mt76) && dev->mt76.hwrro_mode == MT76_HWRRO_V3)
2594 mt76_wr(dev, MT_RRO_3_0_EMU_CONF, MT_RRO_3_0_EMU_CONF_EN_MASK);2562 mt76_set(dev, MT_RRO_3_0_EMU_CONF, MT_RRO_3_0_EMU_CONF_EN_MASK);
2595 2563
2596 if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {2564 if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
2597 u32 wed_irq_mask = MT_INT_TX_DONE_BAND2 |2565 u32 wed_irq_mask = MT_INT_TX_DONE_BAND2 |
@@ -2610,6 +2578,8 @@ void mt7996_mac_reset_work(struct work_struct *work) · 12 unmodified lines
2610 MT_INT_TX_RX_DONE_EXT);2578 MT_INT_TX_RX_DONE_EXT);
2611 }2579 }
2612 2580
2581 __mt7996_npu_hw_init(dev);
2582
2613 clear_bit(MT76_MCU_RESET, &dev->mphy.state);2583 clear_bit(MT76_MCU_RESET, &dev->mphy.state);
2614 mt7996_for_each_phy(dev, phy)2584 mt7996_for_each_phy(dev, phy)
2615 clear_bit(MT76_RESET, &phy->mt76->state);2585 clear_bit(MT76_RESET, &phy->mt76->state);
@@ -2619,6 +2589,13 @@ void mt7996_mac_reset_work(struct work_struct *work) · 3 unmodified lines
2619 mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))2589 mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
2620 continue;2590 continue;
2621 2591
2592 if (mt76_npu_device_active(&dev->mt76) &&
2593 mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
2594 continue;
2595
2596 if (mt76_queue_is_npu_txfree(&dev->mt76.q_rx[i]))
2597 continue;
2598
2622 napi_enable(&dev->mt76.napi[i]);2599 napi_enable(&dev->mt76.napi[i]);
2623 local_bh_disable();2600 local_bh_disable();
2624 napi_schedule(&dev->mt76.napi[i]);2601 napi_schedule(&dev->mt76.napi[i]);
@@ -2639,8 +2616,6 @@ void mt7996_mac_reset_work(struct work_struct *work) · 14 unmodified lines
2639 2616
2640 mutex_unlock(&dev->mt76.mutex);2617 mutex_unlock(&dev->mt76.mutex);
2641 2618
2642 mt7996_npu_hw_init(dev);
2643
2644 mt7996_for_each_phy(dev, phy)2619 mt7996_for_each_phy(dev, phy)
2645 ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,2620 ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
2646 MT7996_WATCHDOG_TIME);2621 MT7996_WATCHDOG_TIME);
@@ -2737,6 +2712,11 @@ void mt7996_reset(struct mt7996_dev *dev) · 90 unmodified lines
2737 return;2712 return;
2738 }2713 }
2739 2714
2715 if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA) {
2716 set_bit(MT76_MCU_RESET, &dev->mphy.state);
2717 wake_up(&dev->mt76.mcu.wait);
2718 }
2719
2740 queue_work(dev->mt76.wq, &dev->reset_work);2720 queue_work(dev->mt76.wq, &dev->reset_work);
2741 wake_up(&dev->reset_wait);2721 wake_up(&dev->reset_wait);
2742}2722}
@@ -2955,6 +2935,7 @@ void mt7996_mac_work(struct work_struct *work) · 212 unmodified lines
2955 2935
2956 mutex_unlock(&mphy->dev->mutex);2936 mutex_unlock(&mphy->dev->mutex);
2957 2937
2938 mt76_beacon_mon_check(mphy);
2958 mt76_tx_status_check(mphy->dev, false);2939 mt76_tx_status_check(mphy->dev, false);
2959 2940
2960 ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,2941 ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
@@ -2974,7 +2955,7 @@ static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy) · 13 unmodified lines
2974 2955
2975static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)2956static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)
2976{2957{
2977 int err, region;2958 int region;
2978 2959
2979 switch (dev->mt76.region) {2960 switch (dev->mt76.region) {
2980 case NL80211_DFS_ETSI:2961 case NL80211_DFS_ETSI:
@@ -2989,11 +2970,7 @@ static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx) · 8 unmodified lines
2989 break;2970 break;
2990 }2971 }
2991 2972
2992 err = mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region);2973 return mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region);
2993 if (err < 0)
2994 return err;
2995
2996 return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, rdd_idx, 1);
2997}2974}
2998 2975
2999static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy)2976static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy)
@@ -3015,40 +2992,6 @@ static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy) · 15 unmodified lines
3015 return err;2992 return err;
3016}2993}
3017 2994
3018static int
3019mt7996_dfs_init_radar_specs(struct mt7996_phy *phy)
3020{
3021 const struct mt7996_dfs_radar_spec *radar_specs;
3022 struct mt7996_dev *dev = phy->dev;
3023 int err, i;
3024
3025 switch (dev->mt76.region) {
3026 case NL80211_DFS_FCC:
3027 radar_specs = &fcc_radar_specs;
3028 err = mt7996_mcu_set_fcc5_lpn(dev, 8);
3029 if (err < 0)
3030 return err;
3031 break;
3032 case NL80211_DFS_ETSI:
3033 radar_specs = &etsi_radar_specs;
3034 break;
3035 case NL80211_DFS_JP:
3036 radar_specs = &jp_radar_specs;
3037 break;
3038 default:
3039 return -EINVAL;
3040 }
3041
3042 for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) {
3043 err = mt7996_mcu_set_radar_th(dev, i,
3044 &radar_specs->radar_pattern[i]);
3045 if (err < 0)
3046 return err;
3047 }
3048
3049 return mt7996_mcu_set_pulse_th(dev, &radar_specs->pulse_th);
3050}
3051
3052int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)2995int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)
3053{2996{
3054 struct mt7996_dev *dev = phy->dev;2997 struct mt7996_dev *dev = phy->dev;
@@ -3068,10 +3011,6 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy) · 13 unmodified lines
3068 goto stop;3011 goto stop;
3069 3012
3070 if (prev_state <= MT_DFS_STATE_DISABLED) {3013 if (prev_state <= MT_DFS_STATE_DISABLED) {
3071 err = mt7996_dfs_init_radar_specs(phy);
3072 if (err < 0)
3073 return err;
3074
3075 err = mt7996_dfs_start_radar_detector(phy);3014 err = mt7996_dfs_start_radar_detector(phy);
3076 if (err < 0)3015 if (err < 0)
3077 return err;3016 return err;
drivers/net/wireless/mediatek/mt76/mt7996/mac.h+0−5
@@ -37,9 +37,4 @@ struct mt7996_dfs_pattern { · 36 unmodified lines
37 u32 min_stgpr_diff;37 u32 min_stgpr_diff;
38} __packed;38} __packed;
39 39
40struct mt7996_dfs_radar_spec {
41 struct mt7996_dfs_pulse pulse_th;
42 struct mt7996_dfs_pattern radar_pattern[16];
43};
44
45#endif40#endif
drivers/net/wireless/mediatek/mt76/mt7996/main.c+323−94
@@ -56,7 +56,7 @@ static int mt7996_start(struct ieee80211_hw *hw) · 55 unmodified lines
56 56
57 mutex_lock(&dev->mt76.mutex);57 mutex_lock(&dev->mt76.mutex);
58 ret = mt7996_mcu_set_hdr_trans(dev, true);58 ret = mt7996_mcu_set_hdr_trans(dev, true);
59 if (!ret && is_mt7992(&dev->mt76)) {59 if (!ret && !is_mt7996(&dev->mt76)) {
60 u8 queue = mt76_connac_lmac_mapping(IEEE80211_AC_VI);60 u8 queue = mt76_connac_lmac_mapping(IEEE80211_AC_VI);
61 61
62 ret = mt7996_mcu_cp_support(dev, queue);62 ret = mt7996_mcu_cp_support(dev, queue);
@@ -79,6 +79,7 @@ static void mt7996_stop_phy(struct mt7996_phy *phy) · 16 unmodified lines
79 79
80 mutex_lock(&dev->mt76.mutex);80 mutex_lock(&dev->mt76.mutex);
81 81
82 mt7996_mcu_rdd_resume_tx(phy);
82 mt7996_mcu_set_radio_en(phy, false);83 mt7996_mcu_set_radio_en(phy, false);
83 84
84 clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);85 clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
@@ -238,10 +239,13 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, · 153 unmodified lines
238 link_conf = &vif->bss_conf;239 link_conf = &vif->bss_conf;
239 240
240 if (cmd == SET_KEY && !sta && !link->mt76.cipher) {241 if (cmd == SET_KEY && !sta && !link->mt76.cipher) {
242 struct mt7996_phy *phy = mt7996_vif_link_phy(link);
243
241 link->mt76.cipher =244 link->mt76.cipher =
242 mt76_connac_mcu_get_cipher(key->cipher);245 mt76_connac_mcu_get_cipher(key->cipher);
243 mt7996_mcu_add_bss_info(link->phy, vif, link_conf,246 if (phy)
244 &link->mt76, msta_link, true);247 mt7996_mcu_add_bss_info(phy, vif, link_conf,
248 &link->mt76, msta_link, true);
245 }249 }
246 250
247 if (cmd == SET_KEY)251 if (cmd == SET_KEY)
@@ -300,9 +304,16 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, · 52 unmodified lines
300 .cmd = SET_KEY,304 .cmd = SET_KEY,
301 .link_id = link_conf->link_id,305 .link_id = link_conf->link_id,
302 };306 };
303 struct mt76_txq *mtxq;
304 int mld_idx, idx, ret;307 int mld_idx, idx, ret;
305 308
309 if ((mvif->mt76.valid_links & BIT(link_conf->link_id)) &&
310 !mlink->offchannel) {
311 if (vif->type == NL80211_IFTYPE_AP)
312 return mt7996_mcu_mld_link_oper(dev, link_conf, link,
313 true);
314 return 0;
315 }
316
306 mlink->idx = __ffs64(~dev->mt76.vif_mask);317 mlink->idx = __ffs64(~dev->mt76.vif_mask);
307 if (mlink->idx >= mt7996_max_interface_num(dev))318 if (mlink->idx >= mt7996_max_interface_num(dev))
308 return -ENOSPC;319 return -ENOSPC;
@@ -316,7 +327,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, · 7 unmodified lines
316 return -ENOSPC;327 return -ENOSPC;
317 328
318 link->mld_idx = mld_idx;329 link->mld_idx = mld_idx;
319 link->phy = phy;
320 mlink->omac_idx = idx;330 mlink->omac_idx = idx;
321 mlink->band_idx = band_idx;331 mlink->band_idx = band_idx;
322 mlink->wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3;332 mlink->wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3;
@@ -343,11 +353,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, · 20 unmodified lines
343 mt7996_mac_wtbl_update(dev, idx,353 mt7996_mac_wtbl_update(dev, idx,
344 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);354 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
345 355
346 if (vif->txq) {
347 mtxq = (struct mt76_txq *)vif->txq->drv_priv;
348 mtxq->wcid = idx;
349 }
350
351 if (vif->type != NL80211_IFTYPE_AP &&356 if (vif->type != NL80211_IFTYPE_AP &&
352 (!mlink->omac_idx || mlink->omac_idx > 3))357 (!mlink->omac_idx || mlink->omac_idx > 3))
353 vif->offload_flags = 0;358 vif->offload_flags = 0;
@@ -370,56 +375,66 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, · 16 unmodified lines
370 375
371 ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);376 ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);
372 377
373 if (!mlink->wcid->offchannel &&378 if (!mlink->wcid->offchannel) {
374 mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED)379 if (vif->txq &&
375 mvif->mt76.deflink_id = link_conf->link_id;380 mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED) {
381 struct mt76_txq *mtxq;
382
383 mtxq = (struct mt76_txq *)vif->txq->drv_priv;
384 mvif->mt76.deflink_id = link_conf->link_id;
385 mtxq->wcid = idx;
386 }
387 mvif->mt76.valid_links |= BIT(link_conf->link_id);
388 }
389
390 if (vif->type == NL80211_IFTYPE_STATION) {
391 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
392
393 if (vif->cfg.assoc && link_conf->beacon_int) {
394 mlink->beacon_mon_interval =
395 msecs_to_jiffies(ieee80211_tu_to_usec(
396 link_conf->beacon_int) / 1000);
397 WRITE_ONCE(mlink->beacon_mon_last, jiffies);
398 }
399 }
376 400
377 return 0;401 return 0;
378}402}
379 403
380void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,404static void mt7996_vif_link_destroy(struct mt7996_phy *phy,
381 struct ieee80211_bss_conf *link_conf,405 struct mt7996_vif_link *link,
382 struct mt76_vif_link *mlink)406 struct ieee80211_vif *vif,
407 struct ieee80211_bss_conf *link_conf)
383{408{
384 struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
385 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;409 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
386 struct mt7996_sta_link *msta_link = &link->msta_link;410 struct mt7996_sta_link *msta_link = &link->msta_link;
387 struct mt7996_phy *phy = mphy->priv;411 unsigned int link_id = msta_link->wcid.link_id;
388 struct mt7996_dev *dev = phy->dev;412 struct mt76_vif_link *mlink = &link->mt76;
389 struct mt7996_key_iter_data it = {413 struct mt7996_key_iter_data it = {
390 .cmd = SET_KEY,414 .cmd = SET_KEY,
391 .link_id = link_conf->link_id,415 .link_id = link_id,
392 };416 };
417 struct mt7996_dev *dev = phy->dev;
393 int idx = msta_link->wcid.idx;418 int idx = msta_link->wcid.idx;
394 419
420 if (!link_conf)
421 link_conf = &vif->bss_conf;
422
395 if (!mlink->wcid->offchannel)423 if (!mlink->wcid->offchannel)
396 ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);424 ieee80211_iter_keys(phy->mt76->hw, vif, mt7996_key_iter, &it);
397 425
398 mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,426 mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
399 CONN_STATE_DISCONNECT, false);427 CONN_STATE_DISCONNECT, false);
400 mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, false);428 mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, false);
401
402 mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false);429 mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false);
403 430
404 rcu_assign_pointer(dev->mt76.wcid[idx], NULL);431 rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
405 432
406 if (!mlink->wcid->offchannel &&
407 mvif->mt76.deflink_id == link_conf->link_id) {
408 struct ieee80211_bss_conf *iter;
409 unsigned int link_id;
410
411 mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED;
412 for_each_vif_active_link(vif, iter, link_id) {
413 if (link_id != IEEE80211_LINK_UNSPECIFIED) {
414 mvif->mt76.deflink_id = link_id;
415 break;
416 }
417 }
418 }
419
420 dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);433 dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);
421 dev->mld_idx_mask &= ~BIT_ULL(link->mld_idx);434 dev->mld_idx_mask &= ~BIT_ULL(link->mld_idx);
422 phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);435 phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
436 if (!mlink->wcid->offchannel)
437 mvif->mt76.valid_links &= ~BIT(link_id);
423 438
424 spin_lock_bh(&dev->mt76.sta_poll_lock);439 spin_lock_bh(&dev->mt76.sta_poll_lock);
425 if (!list_empty(&msta_link->wcid.poll_list))440 if (!list_empty(&msta_link->wcid.poll_list))
@@ -427,6 +442,58 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif, · 1 unmodified line
427 spin_unlock_bh(&dev->mt76.sta_poll_lock);442 spin_unlock_bh(&dev->mt76.sta_poll_lock);
428 443
429 mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);444 mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
445
446 if (mlink != (struct mt76_vif_link *)vif->drv_priv &&
447 !mlink->wcid->offchannel) {
448 rcu_assign_pointer(mlink->mvif->link[link_id], NULL);
449 kfree_rcu(mlink, rcu_head);
450 }
451}
452
453void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
454 struct ieee80211_bss_conf *link_conf,
455 struct mt76_vif_link *mlink)
456{
457 struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
458 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
459 struct mt7996_sta_link *msta_link = &link->msta_link;
460 unsigned int link_id = msta_link->wcid.link_id;
461 struct mt7996_phy *phy = mphy->priv;
462
463 /* Hw requires to destroy active links tearing down the interface, so
464 * postpone it removing the interface.
465 */
466 if (mlink->wcid->offchannel) {
467 mt7996_vif_link_destroy(phy, link, vif, link_conf);
468 } else {
469 if (vif->type == NL80211_IFTYPE_AP) {
470 mt7996_mcu_mld_reconf_stop_link(phy->dev, vif,
471 BIT(link_id));
472 mt7996_mcu_mld_link_oper(phy->dev, link_conf, link,
473 false);
474 }
475
476 if (vif->txq && mvif->mt76.deflink_id == link_id) {
477 struct ieee80211_bss_conf *iter;
478 struct mt76_txq *mtxq;
479
480 mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED;
481 mtxq = (struct mt76_txq *)vif->txq->drv_priv;
482 /* Primary link will be removed, look for a new one */
483 for_each_vif_active_link(vif, iter, link_id) {
484 if (link_id == msta_link->wcid.link_id)
485 continue;
486
487 link = mt7996_vif_link(phy->dev, vif, link_id);
488 if (!link)
489 continue;
490
491 mtxq->wcid = link->msta_link.wcid.idx;
492 mvif->mt76.deflink_id = link_id;
493 break;
494 }
495 }
496 }
430}497}
431 498
432static void mt7996_phy_set_rxfilter(struct mt7996_phy *phy)499static void mt7996_phy_set_rxfilter(struct mt7996_phy *phy)
@@ -472,6 +539,8 @@ static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled) · 39 unmodified lines
472 539
473 mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx),540 mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx),
474 MT_DMA_DCR0_RXD_G5_EN, enabled);541 MT_DMA_DCR0_RXD_G5_EN, enabled);
542 mt76_rmw_field(dev, MT_MDP_DCR0,
543 MT_MDP_DCR0_RX_HDR_TRANS_EN, !enabled);
475 mt7996_phy_set_rxfilter(phy);544 mt7996_phy_set_rxfilter(phy);
476 mt7996_mcu_set_sniffer_mode(phy, enabled);545 mt7996_mcu_set_sniffer_mode(phy, enabled);
477}546}
@@ -530,10 +599,29 @@ static void mt7996_remove_iter(void *data, u8 *mac, struct ieee80211_vif *vif) · 52 unmodified lines
530static void mt7996_remove_interface(struct ieee80211_hw *hw,599static void mt7996_remove_interface(struct ieee80211_hw *hw,
531 struct ieee80211_vif *vif)600 struct ieee80211_vif *vif)
532{601{
602 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
603 unsigned long rem_links = mvif->mt76.valid_links;
533 struct mt7996_dev *dev = mt7996_hw_dev(hw);604 struct mt7996_dev *dev = mt7996_hw_dev(hw);
534 struct mt7996_radio_data rdata = {};605 struct mt7996_radio_data rdata = {};
606 unsigned int link_id;
535 int i;607 int i;
536 608
609 /* Remove all active links */
610 for_each_set_bit(link_id, &rem_links, IEEE80211_MLD_MAX_NUM_LINKS) {
611 struct mt7996_vif_link *link;
612 struct mt7996_phy *phy;
613
614 link = mt7996_vif_link(dev, vif, link_id);
615 if (!link)
616 continue;
617
618 phy = __mt7996_phy(dev, link->msta_link.wcid.phy_idx);
619 if (!phy)
620 continue;
621
622 mt7996_vif_link_destroy(phy, link, vif, NULL);
623 }
624
537 ieee80211_iterate_active_interfaces_mtx(hw, 0, mt7996_remove_iter,625 ieee80211_iterate_active_interfaces_mtx(hw, 0, mt7996_remove_iter,
538 &rdata);626 &rdata);
539 mt76_vif_cleanup(&dev->mt76, vif);627 mt76_vif_cleanup(&dev->mt76, vif);
@@ -811,15 +899,24 @@ mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 271 unmodified lines
811 899
812 for_each_vif_active_link(vif, link_conf, link_id) {900 for_each_vif_active_link(vif, link_conf, link_id) {
813 struct mt7996_vif_link *link;901 struct mt7996_vif_link *link;
902 struct mt7996_phy *phy;
814 903
815 link = mt7996_vif_link(dev, vif, link_id);904 link = mt7996_vif_link(dev, vif, link_id);
816 if (!link)905 if (!link)
817 continue;906 continue;
818 907
819 if (!link->phy)908 if (vif->type == NL80211_IFTYPE_STATION) {
909 link->mt76.beacon_mon_interval =
910 msecs_to_jiffies(ieee80211_tu_to_usec(
911 link_conf->beacon_int) / 1000);
912 WRITE_ONCE(link->mt76.beacon_mon_last, jiffies);
913 }
914
915 phy = mt7996_vif_link_phy(link);
916 if (!phy)
820 continue;917 continue;
821 918
822 mt7996_mcu_add_bss_info(link->phy, vif, link_conf,919 mt7996_mcu_add_bss_info(phy, vif, link_conf,
823 &link->mt76, &link->msta_link,920 &link->mt76, &link->msta_link,
824 true);921 true);
825 mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,922 mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
@@ -828,6 +925,20 @@ mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 2 unmodified lines
828 }925 }
829 }926 }
830 927
928 if ((changed & BSS_CHANGED_ASSOC) && !vif->cfg.assoc &&
929 vif->type == NL80211_IFTYPE_STATION) {
930 struct ieee80211_bss_conf *link_conf;
931 unsigned long link_id;
932
933 for_each_vif_active_link(vif, link_conf, link_id) {
934 struct mt7996_vif_link *link;
935
936 link = mt7996_vif_link(dev, vif, link_id);
937 if (link)
938 link->mt76.beacon_mon_interval = 0;
939 }
940 }
941
831 mutex_unlock(&dev->mt76.mutex);942 mutex_unlock(&dev->mt76.mutex);
832}943}
833 944
@@ -864,6 +975,10 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 30 unmodified lines
864 !!(changed & BSS_CHANGED_BSSID));975 !!(changed & BSS_CHANGED_BSSID));
865 }976 }
866 977
978 if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
979 mt7996_mcu_set_protection(phy, link, info->ht_operation_mode,
980 info->use_cts_prot);
981
867 if (changed & BSS_CHANGED_ERP_SLOT) {982 if (changed & BSS_CHANGED_ERP_SLOT) {
868 int slottime = info->use_short_slot ? 9 : 20;983 int slottime = info->use_short_slot ? 9 : 20;
869 984
@@ -927,10 +1042,82 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw, · 57 unmodified lines
927 struct cfg80211_chan_def *chandef)1042 struct cfg80211_chan_def *chandef)
928{1043{
929 struct mt7996_dev *dev = mt7996_hw_dev(hw);1044 struct mt7996_dev *dev = mt7996_hw_dev(hw);
1045 struct mt7996_phy *phy = mt7996_band_phy(dev, chandef->chan->band);
1046 struct ieee80211_bss_conf *link_conf;
1047 unsigned int link_id;
930 1048
931 mutex_lock(&dev->mt76.mutex);1049 mutex_lock(&dev->mt76.mutex);
932 mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf, vif->bss_conf.enable_beacon);1050
1051 for_each_vif_active_link(vif, link_conf, link_id) {
1052 struct mt7996_vif_link *link;
1053 struct mt7996_phy *link_phy;
1054
1055 link = mt7996_vif_link(dev, vif, link_id);
1056 if (!link)
1057 continue;
1058
1059 link_phy = mt7996_vif_link_phy(link);
1060 if (link_phy != phy)
1061 continue;
1062
1063 /* Reset beacon when channel switch triggered during CAC to let
1064 * FW correctly perform CSA countdown
1065 */
1066 if (!cfg80211_reg_can_beacon(hw->wiphy, &phy->mt76->chandef,
1067 vif->type))
1068 mt7996_mcu_add_beacon(hw, vif, link_conf, false);
1069
1070 mt7996_mcu_add_beacon(hw, vif, link_conf, true);
1071 break;
1072 }
1073
1074 mutex_unlock(&dev->mt76.mutex);
1075}
1076
1077static int
1078mt7996_post_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1079 struct ieee80211_bss_conf *link_conf)
1080{
1081 struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper;
1082 struct mt7996_dev *dev = mt7996_hw_dev(hw);
1083 struct mt7996_phy *phy = mt7996_band_phy(dev, chandef->chan->band);
1084 struct mt7996_vif_link *link;
1085 int ret = -EINVAL;
1086
1087 mutex_lock(&dev->mt76.mutex);
1088
1089 link = mt7996_vif_conf_link(dev, vif, link_conf);
1090 if (!link)
1091 goto out;
1092
1093 ret = mt7996_mcu_update_bss_rfch(phy, link);
1094 if (ret)
1095 goto out;
1096
1097 ieee80211_iterate_stations_mtx(hw, mt7996_mcu_update_sta_rec_bw, link);
1098
1099 ret = mt7996_mcu_rdd_resume_tx(phy);
1100
1101out:
933 mutex_unlock(&dev->mt76.mutex);1102 mutex_unlock(&dev->mt76.mutex);
1103
1104 return ret;
1105}
1106
1107static void
1108mt7996_sta_init_txq_wcid(struct ieee80211_sta *sta, int idx)
1109{
1110 int i;
1111
1112 for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
1113 struct mt76_txq *mtxq;
1114
1115 if (!sta->txq[i])
1116 continue;
1117
1118 mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
1119 mtxq->wcid = idx;
1120 }
934}1121}
935 1122
936static int1123static int
@@ -941,30 +1128,22 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev, · 4 unmodified lines
941{1128{
942 struct ieee80211_sta *sta = link_sta->sta;1129 struct ieee80211_sta *sta = link_sta->sta;
943 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;1130 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
944 struct mt7996_phy *phy = link->phy;1131 struct mt7996_phy *phy = mt7996_vif_link_phy(link);
945 struct mt7996_sta_link *msta_link;1132 struct mt7996_sta_link *msta_link;
946 int idx;1133 int idx;
947 1134
1135 if (!phy)
1136 return -EINVAL;
1137
948 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);1138 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
949 if (idx < 0)1139 if (idx < 0)
950 return -ENOSPC;1140 return -ENOSPC;
951 1141
952 if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {1142 if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
953 int i;
954
955 msta_link = &msta->deflink;1143 msta_link = &msta->deflink;
956 msta->deflink_id = link_id;1144 msta->deflink_id = link_id;
957 msta->seclink_id = msta->deflink_id;1145 msta->seclink_id = msta->deflink_id;
958 1146 mt7996_sta_init_txq_wcid(sta, idx);
959 for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
960 struct mt76_txq *mtxq;
961
962 if (!sta->txq[i])
963 continue;
964
965 mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
966 mtxq->wcid = idx;
967 }
968 } else {1147 } else {
969 msta_link = kzalloc_obj(*msta_link);1148 msta_link = kzalloc_obj(*msta_link);
970 if (!msta_link)1149 if (!msta_link)
@@ -1000,9 +1179,17 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev, · 29 unmodified lines
1000 return 0;1179 return 0;
1001}1180}
1002 1181
1003void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,1182void mt7996_mac_sta_remove_link(struct mt7996_dev *dev,
1004 struct mt7996_sta_link *msta_link)1183 struct ieee80211_sta *sta,
1184 unsigned int link_id, bool flush)
1005{1185{
1186 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
1187 struct mt7996_sta_link *msta_link;
1188
1189 msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
1190 if (!msta_link)
1191 return;
1192
1006 spin_lock_bh(&dev->mt76.sta_poll_lock);1193 spin_lock_bh(&dev->mt76.sta_poll_lock);
1007 if (!list_empty(&msta_link->wcid.poll_list))1194 if (!list_empty(&msta_link->wcid.poll_list))
1008 list_del_init(&msta_link->wcid.poll_list);1195 list_del_init(&msta_link->wcid.poll_list);
@@ -1011,51 +1198,61 @@ void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev, · 2 unmodified lines
1011 spin_unlock_bh(&dev->mt76.sta_poll_lock);1198 spin_unlock_bh(&dev->mt76.sta_poll_lock);
1012 1199
1013 mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);1200 mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
1014 mt76_wcid_mask_clear(dev->mt76.wcid_mask, msta_link->wcid.idx);
1015}
1016
1017static void
1018mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
1019 struct ieee80211_sta *sta, unsigned long links)
1020{
1021 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
1022 struct mt76_dev *mdev = &dev->mt76;
1023 unsigned int link_id;
1024 1201
1025 for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {1202 if (msta_link->wcid.link_valid) {
1026 struct mt7996_sta_link *msta_link = NULL;1203 struct mt7996_phy *phy;
1027 struct mt7996_vif_link *link;
1028 struct mt76_phy *mphy;
1029
1030 msta_link = rcu_replace_pointer(msta->link[link_id], msta_link,
1031 lockdep_is_held(&mdev->mutex));
1032 if (!msta_link)
1033 continue;
1034 1204
1035 mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,1205 mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
1036 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);1206 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
1037 1207
1038 mt7996_mac_sta_deinit_link(dev, msta_link);1208 phy = __mt7996_phy(dev, msta_link->wcid.phy_idx);
1039 link = mt7996_vif_link(dev, vif, link_id);1209 if (phy)
1040 if (!link)1210 phy->mt76->num_sta--;
1041 continue;
1042 1211
1043 mphy = mt76_vif_link_phy(&link->mt76);
1044 if (!mphy)
1045 continue;
1046
1047 mphy->num_sta--;
1048 if (msta->deflink_id == link_id) {1212 if (msta->deflink_id == link_id) {
1049 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;1213 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
1050 continue;1214 if (msta->seclink_id == link_id) {
1215 /* no secondary link available */
1216 msta->seclink_id = msta->deflink_id;
1217 } else {
1218 struct mt7996_sta_link *msta_seclink;
1219
1220 /* switch to the secondary link */
1221 msta_seclink = mt76_dereference(
1222 msta->link[msta->seclink_id],
1223 &dev->mt76);
1224 if (msta_seclink) {
1225 msta->deflink_id = msta->seclink_id;
1226 mt7996_sta_init_txq_wcid(sta,
1227 msta_seclink->wcid.idx);
1228 }
1229 }
1051 } else if (msta->seclink_id == link_id) {1230 } else if (msta->seclink_id == link_id) {
1052 msta->seclink_id = IEEE80211_LINK_UNSPECIFIED;1231 msta->seclink_id = msta->deflink_id;
1053 }1232 }
1233 msta_link->wcid.link_valid = false;
1234 }
1054 1235
1055 kfree_rcu(msta_link, rcu_head);1236 if (flush) {
1237 rcu_assign_pointer(msta->link[link_id], NULL);
1238 rcu_assign_pointer(dev->mt76.wcid[msta_link->wcid.idx], NULL);
1239 mt76_wcid_mask_clear(dev->mt76.wcid_mask, msta_link->wcid.idx);
1240 if (msta_link != &msta->deflink)
1241 kfree_rcu(msta_link, rcu_head);
1056 }1242 }
1057}1243}
1058 1244
1245static void
1246mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
1247 struct ieee80211_sta *sta, unsigned long links,
1248 bool flush)
1249{
1250 unsigned int link_id;
1251
1252 for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS)
1253 mt7996_mac_sta_remove_link(dev, sta, link_id, flush);
1254}
1255
1059static int1256static int
1060mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,1257mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
1061 struct ieee80211_sta *sta, unsigned long new_links)1258 struct ieee80211_sta *sta, unsigned long new_links)
@@ -1067,11 +1264,15 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif, · 5 unmodified lines
1067 for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {1264 for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
1068 struct ieee80211_bss_conf *link_conf;1265 struct ieee80211_bss_conf *link_conf;
1069 struct ieee80211_link_sta *link_sta;1266 struct ieee80211_link_sta *link_sta;
1267 struct mt7996_sta_link *msta_link;
1070 struct mt7996_vif_link *link;1268 struct mt7996_vif_link *link;
1071 struct mt76_phy *mphy;1269 struct mt76_phy *mphy;
1072 1270
1073 if (rcu_access_pointer(msta->link[link_id]))1271 msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
1272 if (msta_link) {
1273 msta_link->wcid.link_valid = true;
1074 continue;1274 continue;
1275 }
1075 1276
1076 link_conf = link_conf_dereference_protected(vif, link_id);1277 link_conf = link_conf_dereference_protected(vif, link_id);
1077 if (!link_conf) {1278 if (!link_conf) {
@@ -1108,7 +1309,7 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif, · 30 unmodified lines
1108 return 0;1309 return 0;
1109 1310
1110error_unlink:1311error_unlink:
1111 mt7996_mac_sta_remove_links(dev, vif, sta, new_links);1312 mt7996_mac_sta_remove_links(dev, vif, sta, new_links, true);
1112 1313
1113 return err;1314 return err;
1114}1315}
@@ -1125,7 +1326,7 @@ mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 10 unmodified lines
1125 1326
1126 mutex_lock(&dev->mt76.mutex);1327 mutex_lock(&dev->mt76.mutex);
1127 1328
1128 mt7996_mac_sta_remove_links(dev, vif, sta, rem);1329 mt7996_mac_sta_remove_links(dev, vif, sta, rem, false);
1129 ret = mt7996_mac_sta_add_links(dev, vif, sta, add);1330 ret = mt7996_mac_sta_add_links(dev, vif, sta, add);
1130 1331
1131 mutex_unlock(&dev->mt76.mutex);1332 mutex_unlock(&dev->mt76.mutex);
@@ -1234,10 +1435,12 @@ static void · 102 unmodified lines
1234mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,1435mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,
1235 struct ieee80211_sta *sta)1436 struct ieee80211_sta *sta)
1236{1437{
1237 unsigned long links = sta->valid_links ? sta->valid_links : BIT(0);1438 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
1439 int i;
1238 1440
1239 mutex_lock(&dev->mt76.mutex);1441 mutex_lock(&dev->mt76.mutex);
1240 mt7996_mac_sta_remove_links(dev, vif, sta, links);1442 for (i = 0; i < ARRAY_SIZE(msta->link); i++)
1443 mt7996_mac_sta_remove_link(dev, sta, i, true);
1241 mutex_unlock(&dev->mt76.mutex);1444 mutex_unlock(&dev->mt76.mutex);
1242}1445}
1243 1446
@@ -1489,8 +1692,8 @@ mt7996_get_stats(struct ieee80211_hw *hw, · 245 unmodified lines
1489 1692
1490u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link)1693u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link)
1491{1694{
1695 struct mt7996_phy *phy = mt7996_vif_link_phy(link);
1492 struct mt7996_dev *dev = mt7996_hw_dev(hw);1696 struct mt7996_dev *dev = mt7996_hw_dev(hw);
1493 struct mt7996_phy *phy = link->phy;
1494 union {1697 union {
1495 u64 t64;1698 u64 t64;
1496 u32 t32[2];1699 u32 t32[2];
@@ -1549,7 +1752,7 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 52 unmodified lines
1549 1752
1550 n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_01753 n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
1551 : link->mt76.omac_idx;1754 : link->mt76.omac_idx;
1552 phy = link->phy;1755 phy = mt7996_vif_link_phy(link);
1553 if (!phy)1756 if (!phy)
1554 goto unlock;1757 goto unlock;
1555 1758
@@ -1583,7 +1786,7 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 27 unmodified lines
1583 if (!link)1786 if (!link)
1584 goto unlock;1787 goto unlock;
1585 1788
1586 phy = link->phy;1789 phy = mt7996_vif_link_phy(link);
1587 if (!phy)1790 if (!phy)
1588 goto unlock;1791 goto unlock;
1589 1792
@@ -1713,9 +1916,14 @@ static void mt7996_link_rate_ctrl_update(void *data, · 123 unmodified lines
1713 struct mt7996_sta_link *msta_link)1916 struct mt7996_sta_link *msta_link)
1714{1917{
1715 struct mt7996_sta *msta = msta_link->sta;1918 struct mt7996_sta *msta = msta_link->sta;
1716 struct mt7996_dev *dev = msta->vif->deflink.phy->dev;1919 struct mt7996_phy *phy = mt7996_vif_link_phy(&msta->vif->deflink);
1920 struct mt7996_dev *dev;
1717 u32 *changed = data;1921 u32 *changed = data;
1718 1922
1923 if (!phy)
1924 return;
1925
1926 dev = phy->dev;
1719 spin_lock_bh(&dev->mt76.sta_poll_lock);1927 spin_lock_bh(&dev->mt76.sta_poll_lock);
1720 1928
1721 msta_link->changed |= *changed;1929 msta_link->changed |= *changed;
@@ -2204,6 +2412,10 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw, · 482 unmodified lines
2204 path->mtk_wdma.wdma_idx = wed->wdma_idx;2412 path->mtk_wdma.wdma_idx = wed->wdma_idx;
2205 else2413 else
2206#endif2414#endif
2415 if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76) &&
2416 msta_link->wcid.phy_idx == MT_BAND2)
2417 path->mtk_wdma.wdma_idx = 1;
2418 else
2207 path->mtk_wdma.wdma_idx = link->mt76.band_idx;2419 path->mtk_wdma.wdma_idx = link->mt76.band_idx;
2208 path->mtk_wdma.bss = link->mt76.idx;2420 path->mtk_wdma.bss = link->mt76.idx;
2209 path->mtk_wdma.queue = 0;2421 path->mtk_wdma.queue = 0;
@@ -2275,6 +2487,21 @@ mt7996_reconfig_complete(struct ieee80211_hw *hw, · 65 unmodified lines
2275 MT7996_WATCHDOG_TIME);2487 MT7996_WATCHDOG_TIME);
2276}2488}
2277 2489
2490static int
2491mt7996_set_eml_op_mode(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2492 struct ieee80211_sta *sta,
2493 struct ieee80211_eml_params *eml_params)
2494{
2495 struct mt7996_dev *dev = mt7996_hw_dev(hw);
2496 int ret;
2497
2498 mutex_lock(&dev->mt76.mutex);
2499 ret = mt7996_mcu_set_emlsr_mode(dev, vif, sta, eml_params);
2500 mutex_unlock(&dev->mt76.mutex);
2501
2502 return ret;
2503}
2504
2278const struct ieee80211_ops mt7996_ops = {2505const struct ieee80211_ops mt7996_ops = {
2279 .add_chanctx = mt76_add_chanctx,2506 .add_chanctx = mt76_add_chanctx,
2280 .remove_chanctx = mt76_remove_chanctx,2507 .remove_chanctx = mt76_remove_chanctx,
@@ -2306,6 +2533,7 @@ const struct ieee80211_ops mt7996_ops = { · 25 unmodified lines
2306 .release_buffered_frames = mt76_release_buffered_frames,2533 .release_buffered_frames = mt76_release_buffered_frames,
2307 .get_txpower = mt7996_get_txpower,2534 .get_txpower = mt7996_get_txpower,
2308 .channel_switch_beacon = mt7996_channel_switch_beacon,2535 .channel_switch_beacon = mt7996_channel_switch_beacon,
2536 .post_channel_switch = mt7996_post_channel_switch,
2309 .get_stats = mt7996_get_stats,2537 .get_stats = mt7996_get_stats,
2310 .get_et_sset_count = mt7996_get_et_sset_count,2538 .get_et_sset_count = mt7996_get_et_sset_count,
2311 .get_et_stats = mt7996_get_et_stats,2539 .get_et_stats = mt7996_get_et_stats,
@@ -2337,4 +2565,5 @@ const struct ieee80211_ops mt7996_ops = { · 25 unmodified lines
2337 .change_vif_links = mt7996_change_vif_links,2565 .change_vif_links = mt7996_change_vif_links,
2338 .change_sta_links = mt7996_mac_sta_change_links,2566 .change_sta_links = mt7996_mac_sta_change_links,
2339 .reconfig_complete = mt7996_reconfig_complete,2567 .reconfig_complete = mt7996_reconfig_complete,
2568 .set_eml_op_mode = mt7996_set_eml_op_mode,
2340};2569};
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c+685−138
@@ -18,6 +18,9 @@ · 17 unmodified lines
18 case MT7992_VAR_TYPE_23: \18 case MT7992_VAR_TYPE_23: \
19 _fw = MT7992_##name##_23; \19 _fw = MT7992_##name##_23; \
20 break; \20 break; \
21 case MT7992_VAR_TYPE_24: \
22 _fw = MT7992_##name##_24; \
23 break; \
21 default: \24 default: \
22 _fw = MT7992_##name; \25 _fw = MT7992_##name; \
23 } \26 } \
@@ -125,9 +128,16 @@ mt7996_mcu_set_sta_he_mcs(struct ieee80211_link_sta *link_sta, · 101 unmodified lines
125 struct mt7996_vif_link *link,128 struct mt7996_vif_link *link,
126 __le16 *he_mcs, u16 mcs_map)129 __le16 *he_mcs, u16 mcs_map)
127{130{
131 struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76);
128 int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss;132 int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss;
129 enum nl80211_band band = link->phy->mt76->chandef.chan->band;133 enum nl80211_band band;
130 const u16 *mask = link->bitrate_mask.control[band].he_mcs;134 const u16 *mask;
135
136 if (!mphy)
137 return;
138
139 band = mphy->chandef.chan->band;
140 mask = link->bitrate_mask.control[band].he_mcs;
131 141
132 for (nss = 0; nss < max_nss; nss++) {142 for (nss = 0; nss < max_nss; nss++) {
133 int mcs;143 int mcs;
@@ -209,6 +219,7 @@ static int · 75 unmodified lines
209mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd,219mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd,
210 struct sk_buff *skb, int seq)220 struct sk_buff *skb, int seq)
211{221{
222 struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
212 struct mt7996_mcu_rxd *rxd;223 struct mt7996_mcu_rxd *rxd;
213 struct mt7996_mcu_uni_event *event;224 struct mt7996_mcu_uni_event *event;
214 int mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);225 int mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
@@ -217,6 +228,14 @@ mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd, · 2 unmodified lines
217 if (!skb) {228 if (!skb) {
218 dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",229 dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
219 cmd, seq);230 cmd, seq);
231
232 if (!test_and_set_bit(MT76_MCU_RESET, &dev->mphy.state)) {
233 dev->recovery.restart = true;
234 wake_up(&dev->mt76.mcu.wait);
235 queue_work(dev->mt76.wq, &dev->reset_work);
236 wake_up(&dev->reset_wait);
237 }
238
220 return -ETIMEDOUT;239 return -ETIMEDOUT;
221 }240 }
222 241
@@ -233,7 +252,7 @@ mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd, · 10 unmodified lines
233 event = (struct mt7996_mcu_uni_event *)skb->data;252 event = (struct mt7996_mcu_uni_event *)skb->data;
234 ret = le32_to_cpu(event->status);253 ret = le32_to_cpu(event->status);
235 /* skip invalid event */254 /* skip invalid event */
236 if (mcu_cmd != event->cid)255 if (mcu_cmd != le16_to_cpu(event->cid))
237 ret = -EAGAIN;256 ret = -EAGAIN;
238 } else {257 } else {
239 skb_pull(skb, sizeof(struct mt7996_mcu_rxd));258 skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
@@ -259,7 +278,8 @@ mt7996_mcu_set_timeout(struct mt76_dev *mdev, int cmd) · 19 unmodified lines
259 mdev->mcu.timeout = 2 * HZ;278 mdev->mcu.timeout = 2 * HZ;
260 return;279 return;
261 case MCU_UNI_CMD_EFUSE_CTRL:280 case MCU_UNI_CMD_EFUSE_CTRL:
262 mdev->mcu.timeout = 20 * HZ;281 case MCU_UNI_CMD_EXT_EEPROM_CTRL:
282 mdev->mcu.timeout = 30 * HZ;
263 return;283 return;
264 default:284 default:
265 break;285 break;
@@ -313,13 +333,12 @@ mt7996_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, · 47 unmodified lines
313 uni_txd->pkt_type = MCU_PKT_ID;333 uni_txd->pkt_type = MCU_PKT_ID;
314 uni_txd->seq = seq;334 uni_txd->seq = seq;
315 335
316 if (cmd & __MCU_CMD_FIELD_QUERY)336 uni_txd->option = MCU_CMD_UNI;
317 uni_txd->option = MCU_CMD_UNI_QUERY_ACK;337 if (!(cmd & __MCU_CMD_FIELD_QUERY))
318 else338 uni_txd->option |= MCU_CMD_SET;
319 uni_txd->option = MCU_CMD_UNI_EXT_ACK;
320 339
321 if (mcu_cmd == MCU_UNI_CMD_SDO)340 if (wait_seq)
322 uni_txd->option &= ~MCU_CMD_ACK;341 uni_txd->option |= MCU_CMD_ACK;
323 342
324 if ((cmd & __MCU_CMD_FIELD_WA) && (cmd & __MCU_CMD_FIELD_WM))343 if ((cmd & __MCU_CMD_FIELD_WA) && (cmd & __MCU_CMD_FIELD_WM))
325 uni_txd->s2d_index = MCU_S2D_H2CN;344 uni_txd->s2d_index = MCU_S2D_H2CN;
@@ -390,13 +409,117 @@ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3) · 64 unmodified lines
390 sizeof(req), false);409 sizeof(req), false);
391}410}
392 411
412struct mt7996_mcu_countdown_data {
413 struct mt76_phy *mphy;
414 u8 omac_idx;
415};
416
393static void417static void
394mt7996_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)418mt7996_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
395{419{
396 if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)420 struct mt7996_mcu_countdown_data *cdata = (void *)priv;
421 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
422 struct ieee80211_bss_conf *link_conf = NULL;
423 unsigned long valid_links = vif->valid_links ?: BIT(0);
424 unsigned int link_id;
425
426 if (vif->type == NL80211_IFTYPE_STATION)
427 return;
428
429 for_each_set_bit(link_id, &valid_links, IEEE80211_MLD_MAX_NUM_LINKS) {
430 struct mt76_vif_link *mlink =
431 rcu_dereference(mvif->mt76.link[link_id]);
432
433 if (mlink && mlink->band_idx == cdata->mphy->band_idx &&
434 mlink->omac_idx == cdata->omac_idx) {
435 link_conf = rcu_dereference(vif->link_conf[link_id]);
436 break;
437 }
438 }
439
440 if (!link_conf || !link_conf->csa_active)
441 return;
442
443 ieee80211_csa_finish(vif, link_conf->link_id);
444}
445
446static void
447mt7996_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
448{
449 struct mt7996_mcu_countdown_data *cdata = (void *)priv;
450 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
451 struct ieee80211_bss_conf *link_conf = NULL;
452 unsigned long valid_links = vif->valid_links ?: BIT(0);
453 unsigned int link_id;
454
455 if (vif->type == NL80211_IFTYPE_STATION)
456 return;
457
458 for_each_set_bit(link_id, &valid_links, IEEE80211_MLD_MAX_NUM_LINKS) {
459 struct mt76_vif_link *mlink =
460 rcu_dereference(mvif->mt76.link[link_id]);
461
462 if (mlink && mlink->band_idx == cdata->mphy->band_idx &&
463 mlink->omac_idx == cdata->omac_idx) {
464 link_conf = rcu_dereference(vif->link_conf[link_id]);
465 break;
466 }
467 }
468
469 if (!link_conf || !link_conf->color_change_active)
470 return;
471
472 ieee80211_color_change_finish(vif, link_conf->link_id);
473}
474
475static void
476mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
477{
478#define UNI_EVENT_IE_COUNTDOWN_CSA 0
479#define UNI_EVENT_IE_COUNTDOWN_BCC 1
480 struct header {
481 u8 band;
482 u8 rsv[3];
483 };
484 struct mt7996_mcu_rxd *rxd = (struct mt7996_mcu_rxd *)skb->data;
485 const char *data = (char *)&rxd[1], *tail;
486 struct header *hdr = (struct header *)data;
487 struct tlv *tlv = (struct tlv *)(data + 4);
488 struct mt7996_mcu_countdown_notify *event;
489 struct mt7996_mcu_countdown_data cdata;
490
491 if (hdr->band >= ARRAY_SIZE(dev->mt76.phys))
397 return;492 return;
398 493
399 ieee80211_csa_finish(vif, 0);494 cdata.mphy = dev->mt76.phys[hdr->band];
495 if (!cdata.mphy)
496 return;
497
498 tail = skb->data + skb->len;
499 data += sizeof(*hdr);
500 while (data + sizeof(*tlv) < tail && le16_to_cpu(tlv->len)) {
501 event = (struct mt7996_mcu_countdown_notify *)tlv->data;
502
503 cdata.omac_idx = event->omac_idx;
504
505 switch (le16_to_cpu(tlv->tag)) {
506 case UNI_EVENT_IE_COUNTDOWN_CSA:
507 ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
508 IEEE80211_IFACE_ITER_RESUME_ALL,
509 mt7996_mcu_csa_finish, &cdata);
510 break;
511 case UNI_EVENT_IE_COUNTDOWN_BCC:
512 ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
513 IEEE80211_IFACE_ITER_RESUME_ALL,
514 mt7996_mcu_cca_finish, &cdata);
515 break;
516 default:
517 break;
518 }
519
520 data += le16_to_cpu(tlv->len);
521 tlv = (struct tlv *)data;
522 }
400}523}
401 524
402static void525static void
@@ -416,24 +539,32 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) · 13 unmodified lines
416 break;539 break;
417 case MT_RDD_IDX_BACKGROUND:540 case MT_RDD_IDX_BACKGROUND:
418 if (!dev->rdd2_phy)541 if (!dev->rdd2_phy)
419 return;542 goto err;
420 mphy = dev->rdd2_phy->mt76;543 mphy = dev->rdd2_phy->mt76;
421 break;544 break;
422 default:545 default:
423 dev_err(dev->mt76.dev, "Unknown RDD idx %d\n", r->rdd_idx);546 goto err;
424 return;
425 }547 }
426 548
427 if (!mphy)549 if (!mphy)
428 return;550 goto err;
429 551
430 if (r->rdd_idx == MT_RDD_IDX_BACKGROUND)552 if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) {
431 cfg80211_background_radar_event(mphy->hw->wiphy,553 cfg80211_background_radar_event(mphy->hw->wiphy,
432 &dev->rdd2_chandef,554 &dev->rdd2_chandef,
433 GFP_ATOMIC);555 GFP_ATOMIC);
434 else556 } else {
557 struct mt7996_phy *phy = mphy->priv;
558
559 phy->rdd_tx_paused = true;
435 ieee80211_radar_detected(mphy->hw, NULL);560 ieee80211_radar_detected(mphy->hw, NULL);
561 }
436 dev->hw_pattern++;562 dev->hw_pattern++;
563
564 return;
565
566err:
567 dev_err(dev->mt76.dev, "Invalid RDD idx %d\n", r->rdd_idx);
437}568}
438 569
439static void570static void
@@ -476,57 +607,6 @@ out: · 36 unmodified lines
476 wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, len, data);607 wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, len, data);
477}608}
478 609
479static void
480mt7996_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
481{
482 if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
483 return;
484
485 ieee80211_color_change_finish(vif, 0);
486}
487
488static void
489mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
490{
491#define UNI_EVENT_IE_COUNTDOWN_CSA 0
492#define UNI_EVENT_IE_COUNTDOWN_BCC 1
493 struct header {
494 u8 band;
495 u8 rsv[3];
496 };
497 struct mt76_phy *mphy = &dev->mt76.phy;
498 struct mt7996_mcu_rxd *rxd = (struct mt7996_mcu_rxd *)skb->data;
499 const char *data = (char *)&rxd[1], *tail;
500 struct header *hdr = (struct header *)data;
501 struct tlv *tlv = (struct tlv *)(data + 4);
502
503 if (hdr->band >= ARRAY_SIZE(dev->mt76.phys))
504 return;
505
506 if (hdr->band && dev->mt76.phys[hdr->band])
507 mphy = dev->mt76.phys[hdr->band];
508
509 tail = skb->data + skb->len;
510 data += sizeof(struct header);
511 while (data + sizeof(struct tlv) < tail && le16_to_cpu(tlv->len)) {
512 switch (le16_to_cpu(tlv->tag)) {
513 case UNI_EVENT_IE_COUNTDOWN_CSA:
514 ieee80211_iterate_active_interfaces_atomic(mphy->hw,
515 IEEE80211_IFACE_ITER_RESUME_ALL,
516 mt7996_mcu_csa_finish, mphy->hw);
517 break;
518 case UNI_EVENT_IE_COUNTDOWN_BCC:
519 ieee80211_iterate_active_interfaces_atomic(mphy->hw,
520 IEEE80211_IFACE_ITER_RESUME_ALL,
521 mt7996_mcu_cca_finish, mphy->hw);
522 break;
523 }
524
525 data += le16_to_cpu(tlv->len);
526 tlv = (struct tlv *)data;
527 }
528}
529
530static int610static int
531mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rate)611mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rate)
532{612{
@@ -1170,6 +1250,123 @@ out: · 637 unmodified lines
1170 MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);1250 MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
1171}1251}
1172 1252
1253int mt7996_mcu_update_bss_rfch(struct mt7996_phy *phy, struct mt7996_vif_link *link)
1254{
1255 struct mt7996_dev *dev = phy->dev;
1256 struct sk_buff *skb;
1257
1258 skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76,
1259 MT7996_BSS_UPDATE_MAX_SIZE);
1260 if (IS_ERR(skb))
1261 return PTR_ERR(skb);
1262
1263 mt7996_mcu_bss_rfch_tlv(skb, phy);
1264
1265 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
1266 MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
1267}
1268
1269int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *link,
1270 u8 ht_mode, bool use_cts_prot)
1271{
1272 struct mt7996_dev *dev = phy->dev;
1273 struct bss_prot_tlv *prot;
1274 struct sk_buff *skb;
1275 struct tlv *tlv;
1276 enum {
1277 PROT_NONMEMBER = BIT(1),
1278 PROT_20MHZ = BIT(2),
1279 PROT_NONHT_MIXED = BIT(3),
1280 PROT_LEGACY_ERP = BIT(5),
1281 PROT_NONGF_STA = BIT(7),
1282 };
1283
1284 skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76,
1285 MT7996_BSS_UPDATE_MAX_SIZE);
1286 if (IS_ERR(skb))
1287 return PTR_ERR(skb);
1288
1289 tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_PROTECT_INFO,
1290 sizeof(*prot));
1291 prot = (struct bss_prot_tlv *)tlv;
1292
1293 switch (ht_mode & IEEE80211_HT_OP_MODE_PROTECTION) {
1294 case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
1295 prot->prot_mode = cpu_to_le32(PROT_NONMEMBER);
1296 break;
1297 case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
1298 prot->prot_mode = cpu_to_le32(PROT_20MHZ);
1299 break;
1300 case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
1301 prot->prot_mode = cpu_to_le32(PROT_NONHT_MIXED);
1302 break;
1303 }
1304
1305 if (ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
1306 prot->prot_mode |= cpu_to_le32(PROT_NONGF_STA);
1307
1308 if (use_cts_prot)
1309 prot->prot_mode |= cpu_to_le32(PROT_LEGACY_ERP);
1310
1311 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
1312 MCU_WM_UNI_CMD(BSS_INFO_UPDATE), true);
1313}
1314
1315int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev,
1316 struct ieee80211_vif *vif,
1317 struct ieee80211_sta *sta,
1318 struct ieee80211_eml_params *eml_params)
1319{
1320 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
1321 struct mt7996_sta_link *msta_link;
1322 struct sta_rec_eml_op *eml_op;
1323 struct mt7996_vif_link *link;
1324 struct sk_buff *skb;
1325 struct tlv *tlv;
1326
1327 msta_link = mt76_dereference(msta->link[eml_params->link_id],
1328 &dev->mt76);
1329 if (!msta_link)
1330 return -EINVAL;
1331
1332 link = mt7996_vif_link(dev, vif, eml_params->link_id);
1333 if (!link)
1334 return -EINVAL;
1335
1336 skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
1337 &msta_link->wcid,
1338 MT7996_STA_UPDATE_MAX_SIZE);
1339 if (IS_ERR(skb))
1340 return PTR_ERR(skb);
1341
1342 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EML_OP, sizeof(*eml_op));
1343 eml_op = (struct sta_rec_eml_op *)tlv;
1344 eml_op->link_bitmap = 0;
1345
1346 if (eml_params->control & IEEE80211_EML_CTRL_EMLSR_MODE) {
1347 unsigned long link_bitmap = eml_params->link_bitmap;
1348 unsigned int link_id;
1349
1350 for_each_set_bit(link_id, &link_bitmap,
1351 IEEE80211_MLD_MAX_NUM_LINKS) {
1352 struct mt76_phy *mphy;
1353
1354 link = mt7996_vif_link(dev, vif, link_id);
1355 if (!link)
1356 continue;
1357
1358 mphy = mt76_vif_link_phy(&link->mt76);
1359 if (!mphy)
1360 continue;
1361
1362 eml_op->link_bitmap |= BIT(mphy->band_idx);
1363 }
1364 }
1365
1366 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
1367 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
1368}
1369
1173int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,1370int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
1174 struct ieee80211_bss_conf *link_conf)1371 struct ieee80211_bss_conf *link_conf)
1175{1372{
@@ -1779,9 +1976,8 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 603 unmodified lines
1779#define EBF_MODE BIT(0)1976#define EBF_MODE BIT(0)
1780#define IBF_MODE BIT(1)1977#define IBF_MODE BIT(1)
1781#define BF_MAT_ORDER 41978#define BF_MAT_ORDER 4
1979 struct mt7996_phy *phy = mt7996_vif_link_phy(link);
1782 struct ieee80211_vif *vif = link_conf->vif;1980 struct ieee80211_vif *vif = link_conf->vif;
1783 struct mt7996_phy *phy = link->phy;
1784 int tx_ant = hweight16(phy->mt76->chainmask) - 1;
1785 struct sta_rec_bf *bf;1981 struct sta_rec_bf *bf;
1786 struct tlv *tlv;1982 struct tlv *tlv;
1787 static const u8 matrix[BF_MAT_ORDER][BF_MAT_ORDER] = {1983 static const u8 matrix[BF_MAT_ORDER][BF_MAT_ORDER] = {
@@ -1790,8 +1986,12 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 2 unmodified lines
1790 {2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */1986 {2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */
1791 {3, 5, 6, 0} /* 4x1, 4x2, 4x3, 4x4 */1987 {3, 5, 6, 0} /* 4x1, 4x2, 4x3, 4x4 */
1792 };1988 };
1989 int tx_ant;
1793 bool ebf;1990 bool ebf;
1794 1991
1992 if (!phy)
1993 return;
1994
1795 if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))1995 if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
1796 return;1996 return;
1797 1997
@@ -1807,17 +2007,18 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 9 unmodified lines
1807 * ht: iBF only, since mac80211 lacks of eBF support2007 * ht: iBF only, since mac80211 lacks of eBF support
1808 */2008 */
1809 if (link_sta->eht_cap.has_eht)2009 if (link_sta->eht_cap.has_eht)
1810 mt7996_mcu_sta_bfer_eht(link_sta, vif, link->phy, bf, ebf);2010 mt7996_mcu_sta_bfer_eht(link_sta, vif, phy, bf, ebf);
1811 else if (link_sta->he_cap.has_he)2011 else if (link_sta->he_cap.has_he)
1812 mt7996_mcu_sta_bfer_he(link_sta, vif, link->phy, bf, ebf);2012 mt7996_mcu_sta_bfer_he(link_sta, vif, phy, bf, ebf);
1813 else if (link_sta->vht_cap.vht_supported)2013 else if (link_sta->vht_cap.vht_supported)
1814 mt7996_mcu_sta_bfer_vht(link_sta, link->phy, bf, ebf);2014 mt7996_mcu_sta_bfer_vht(link_sta, phy, bf, ebf);
1815 else if (link_sta->ht_cap.ht_supported)2015 else if (link_sta->ht_cap.ht_supported)
1816 mt7996_mcu_sta_bfer_ht(link_sta, link->phy, bf, ebf);2016 mt7996_mcu_sta_bfer_ht(link_sta, phy, bf, ebf);
1817 else2017 else
1818 return;2018 return;
1819 2019
1820 bf->bf_cap = ebf ? EBF_MODE : (dev->ibf ? IBF_MODE : 0);2020 bf->bf_cap = ebf ? EBF_MODE : (dev->ibf ? IBF_MODE : 0);
2021 tx_ant = hweight16(phy->mt76->chainmask) - 1;
1821 if (is_mt7992(&dev->mt76) && tx_ant == 4)2022 if (is_mt7992(&dev->mt76) && tx_ant == 4)
1822 bf->bf_cap |= IBF_MODE;2023 bf->bf_cap |= IBF_MODE;
1823 2024
@@ -1849,11 +2050,14 @@ mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 25 unmodified lines
1849 struct ieee80211_link_sta *link_sta,2050 struct ieee80211_link_sta *link_sta,
1850 struct mt7996_vif_link *link)2051 struct mt7996_vif_link *link)
1851{2052{
1852 struct mt7996_phy *phy = link->phy;2053 struct mt7996_phy *phy = mt7996_vif_link_phy(link);
1853 int tx_ant = hweight8(phy->mt76->antenna_mask) - 1;
1854 struct sta_rec_bfee *bfee;2054 struct sta_rec_bfee *bfee;
1855 struct tlv *tlv;2055 struct tlv *tlv;
1856 u8 nrow = 0;2056 u8 nrow = 0;
2057 int tx_ant;
2058
2059 if (!phy)
2060 return;
1857 2061
1858 if (!(link_sta->vht_cap.vht_supported || link_sta->he_cap.has_he))2062 if (!(link_sta->vht_cap.vht_supported || link_sta->he_cap.has_he))
1859 return;2063 return;
@@ -1877,6 +2081,7 @@ mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 17 unmodified lines
1877 }2081 }
1878 2082
1879 /* reply with identity matrix to avoid 2x2 BF negative gain */2083 /* reply with identity matrix to avoid 2x2 BF negative gain */
2084 tx_ant = hweight8(phy->mt76->antenna_mask) - 1;
1880 bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);2085 bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);
1881}2086}
1882 2087
@@ -2060,6 +2265,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct mt7996_sta *msta, · 177 unmodified lines
2060 struct ieee80211_sta *sta;2265 struct ieee80211_sta *sta;
2061 int ret, nrates = 0, idx;2266 int ret, nrates = 0, idx;
2062 enum nl80211_band band;2267 enum nl80211_band band;
2268 struct mt76_phy *mphy;
2063 bool has_he;2269 bool has_he;
2064 2270
2065#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \2271#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
@@ -2093,7 +2299,11 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct mt7996_sta *msta, · 27 unmodified lines
2093 if (!link_sta)2299 if (!link_sta)
2094 goto error_unlock;2300 goto error_unlock;
2095 2301
2096 band = link->phy->mt76->chandef.chan->band;2302 mphy = mt76_vif_link_phy(&link->mt76);
2303 if (!mphy)
2304 goto error_unlock;
2305
2306 band = mphy->chandef.chan->band;
2097 has_he = link_sta->he_cap.has_he;2307 has_he = link_sta->he_cap.has_he;
2098 mask = link->bitrate_mask;2308 mask = link->bitrate_mask;
2099 idx = msta_link->wcid.idx;2309 idx = msta_link->wcid.idx;
@@ -2173,18 +2383,25 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev, · 73 unmodified lines
2173 struct mt7996_vif_link *link)2383 struct mt7996_vif_link *link)
2174{2384{
2175#define INIT_RCPI 1802385#define INIT_RCPI 180
2176 struct mt76_phy *mphy = link->phy->mt76;2386 struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76);
2177 struct cfg80211_chan_def *chandef = &mphy->chandef;
2178 struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;2387 struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
2179 u32 cap = link_sta->sta->wme ? STA_CAP_WMM : 0;2388 u32 cap = link_sta->sta->wme ? STA_CAP_WMM : 0;
2180 enum nl80211_band band = chandef->chan->band;2389 struct cfg80211_chan_def *chandef;
2181 struct sta_rec_ra_uni *ra;2390 struct sta_rec_ra_uni *ra;
2391 enum nl80211_band band;
2182 struct tlv *tlv;2392 struct tlv *tlv;
2183 u32 supp_rate = link_sta->supp_rates[band];2393 u32 supp_rate;
2394
2395 if (!mphy)
2396 return;
2184 2397
2185 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));2398 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
2186 ra = (struct sta_rec_ra_uni *)tlv;2399 ra = (struct sta_rec_ra_uni *)tlv;
2187 2400
2401 chandef = &mphy->chandef;
2402 band = chandef->chan->band;
2403 supp_rate = link_sta->supp_rates[band];
2404
2188 ra->valid = true;2405 ra->valid = true;
2189 ra->auto_rate = true;2406 ra->auto_rate = true;
2190 ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, link_sta);2407 ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, link_sta);
@@ -2366,6 +2583,72 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct mt7996_vif_link *link, · 175 unmodified lines
2366 sizeof(req), true);2583 sizeof(req), true);
2367}2584}
2368 2585
2586int mt7996_mcu_mld_reconf_stop_link(struct mt7996_dev *dev,
2587 struct ieee80211_vif *vif,
2588 u16 removed_links)
2589{
2590 unsigned long rem_links = removed_links;
2591 struct mld_reconf_stop_link *sl;
2592 struct mld_req_hdr hdr = {};
2593 unsigned int link_id;
2594 struct sk_buff *skb;
2595 struct tlv *tlv;
2596
2597 skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(hdr) + sizeof(*sl));
2598 if (!skb)
2599 return -ENOMEM;
2600
2601 memcpy(hdr.mld_addr, vif->addr, ETH_ALEN);
2602 skb_put_data(skb, &hdr, sizeof(hdr));
2603
2604 tlv = mt7996_mcu_add_uni_tlv(skb, UNI_CMD_MLD_RECONF_STOP_LINK,
2605 sizeof(*sl));
2606 sl = (struct mld_reconf_stop_link *)tlv;
2607 sl->link_bitmap = cpu_to_le16(removed_links);
2608
2609 for_each_set_bit(link_id, &rem_links, IEEE80211_MLD_MAX_NUM_LINKS) {
2610 struct mt7996_vif_link *link;
2611
2612 link = mt7996_vif_link(dev, vif, link_id);
2613 if (!link)
2614 continue;
2615
2616 sl->bss_idx[link_id] = link->mt76.idx;
2617 }
2618
2619 return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WM_UNI_CMD(MLD),
2620 true);
2621}
2622
2623int mt7996_mcu_mld_link_oper(struct mt7996_dev *dev,
2624 struct ieee80211_bss_conf *link_conf,
2625 struct mt7996_vif_link *link, bool add)
2626{
2627 struct ieee80211_vif *vif = link_conf->vif;
2628 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
2629 struct bss_mld_link_op_tlv *mld_op;
2630 struct sk_buff *skb;
2631 struct tlv *tlv;
2632
2633 skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76,
2634 MT7996_BSS_UPDATE_MAX_SIZE);
2635 if (IS_ERR(skb))
2636 return PTR_ERR(skb);
2637
2638 tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_MLD_LINK_OP,
2639 sizeof(*mld_op));
2640 mld_op = (struct bss_mld_link_op_tlv *)tlv;
2641 mld_op->link_operation = add;
2642 mld_op->own_mld_id = link->mld_idx;
2643 mld_op->link_id = link_conf->link_id;
2644 mld_op->group_mld_id = add ? mvif->mld_group_idx : 0xff;
2645 mld_op->remap_idx = add ? mvif->mld_remap_idx : 0xff;
2646 memcpy(mld_op->mac_addr, vif->addr, ETH_ALEN);
2647
2648 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
2649 MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
2650}
2651
2369static void2652static void
2370mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,2653mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
2371 struct ieee80211_vif *vif,2654 struct ieee80211_vif *vif,
@@ -2529,6 +2812,53 @@ int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev, · 157 unmodified lines
2529 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);2812 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
2530}2813}
2531 2814
2815void mt7996_mcu_update_sta_rec_bw(void *data, struct ieee80211_sta *sta)
2816{
2817 struct mt7996_vif_link *link = (struct mt7996_vif_link *)data;
2818 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
2819 struct mt7996_phy *phy = mt7996_vif_link_phy(link);
2820 struct mt7996_sta_link *msta_link;
2821 struct mt7996_dev *dev;
2822 struct ieee80211_bss_conf *link_conf;
2823 struct ieee80211_link_sta *link_sta;
2824 struct ieee80211_vif *vif;
2825 struct sk_buff *skb;
2826 int link_id;
2827
2828 if (!phy)
2829 return;
2830
2831 if (link->mt76.mvif != &msta->vif->mt76)
2832 return;
2833
2834 dev = phy->dev;
2835 link_id = link->msta_link.wcid.link_id;
2836 link_sta = link_sta_dereference_protected(sta, link_id);
2837 if (!link_sta)
2838 return;
2839
2840 msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
2841 if (!msta_link)
2842 return;
2843
2844 vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
2845 link_conf = link_conf_dereference_protected(vif, link_id);
2846 if (!link_conf)
2847 return;
2848
2849 skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
2850 &msta_link->wcid,
2851 MT7996_STA_UPDATE_MAX_SIZE);
2852 if (IS_ERR(skb))
2853 return;
2854
2855 mt7996_mcu_sta_bfer_tlv(dev, skb, link_conf, link_sta, link);
2856 mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, link_conf, link_sta, link);
2857
2858 mt76_mcu_skb_send_msg(&dev->mt76, skb,
2859 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
2860}
2861
2532static int2862static int
2533mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid,2863mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid,
2534 struct sk_buff *skb,2864 struct sk_buff *skb,
@@ -2676,6 +3006,16 @@ mt7996_mcu_beacon_cntdwn(struct sk_buff *rskb, struct sk_buff *skb, · 141 unmodified lines
2676 3006
2677 info = (struct bss_bcn_cntdwn_tlv *)tlv;3007 info = (struct bss_bcn_cntdwn_tlv *)tlv;
2678 info->cnt = skb->data[offs->cntdwn_counter_offs[0]];3008 info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
3009
3010 /* abort the CCA countdown when starting CSA countdown */
3011 if (csa) {
3012 struct bss_bcn_cntdwn_tlv *cca_info;
3013
3014 tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_BCC,
3015 sizeof(*cca_info));
3016 cca_info = (struct bss_bcn_cntdwn_tlv *)tlv;
3017 cca_info->cca.abort = true;
3018 }
2679}3019}
2680 3020
2681static void3021static void
@@ -2768,6 +3108,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 86 unmodified lines
2768{3108{
2769 struct mt7996_dev *dev = mt7996_hw_dev(hw);3109 struct mt7996_dev *dev = mt7996_hw_dev(hw);
2770 struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf);3110 struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf);
3111 struct mt76_phy *mphy = link ? mt76_vif_link_phy(&link->mt76) : NULL;
2771 struct mt76_vif_link *mlink = link ? &link->mt76 : NULL;3112 struct mt76_vif_link *mlink = link ? &link->mt76 : NULL;
2772 struct ieee80211_mutable_offsets offs;3113 struct ieee80211_mutable_offsets offs;
2773 struct ieee80211_tx_info *info;3114 struct ieee80211_tx_info *info;
@@ -2782,7 +3123,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 8 unmodified lines
2782 if (!mlink)3123 if (!mlink)
2783 return -EINVAL;3124 return -EINVAL;
2784 3125
2785 if (link->phy && link->phy->mt76->offchannel)3126 if (mphy && mphy->offchannel)
2786 enabled = false;3127 enabled = false;
2787 3128
2788 rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink,3129 rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink,
@@ -2833,9 +3174,9 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, · 44 unmodified lines
2833{3174{
2834#define OFFLOAD_TX_MODE_SU BIT(0)3175#define OFFLOAD_TX_MODE_SU BIT(0)
2835#define OFFLOAD_TX_MODE_MU BIT(1)3176#define OFFLOAD_TX_MODE_MU BIT(1)
3177 struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76);
2836 struct ieee80211_vif *vif = link_conf->vif;3178 struct ieee80211_vif *vif = link_conf->vif;
2837 struct ieee80211_hw *hw = mt76_hw(dev);3179 struct ieee80211_hw *hw = mt76_hw(dev);
2838 struct mt7996_phy *phy = link->phy;
2839 struct mt76_wcid *wcid = &dev->mt76.global_wcid;3180 struct mt76_wcid *wcid = &dev->mt76.global_wcid;
2840 struct bss_inband_discovery_tlv *discov;3181 struct bss_inband_discovery_tlv *discov;
2841 struct ieee80211_tx_info *info;3182 struct ieee80211_tx_info *info;
@@ -2846,10 +3187,10 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, · 4 unmodified lines
2846 u8 *buf, interval;3187 u8 *buf, interval;
2847 int len;3188 int len;
2848 3189
2849 if (!phy)3190 if (!mphy)
2850 return -EINVAL;3191 return -EINVAL;
2851 3192
2852 chandef = &phy->mt76->chandef;3193 chandef = &mphy->chandef;
2853 band = chandef->chan->band;3194 band = chandef->chan->band;
2854 3195
2855 if (link_conf->nontransmitted)3196 if (link_conf->nontransmitted)
@@ -2887,7 +3228,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, · 31 unmodified lines
2887 info = IEEE80211_SKB_CB(skb);3228 info = IEEE80211_SKB_CB(skb);
2888 info->control.vif = vif;3229 info->control.vif = vif;
2889 info->band = band;3230 info->band = band;
2890 info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);3231 info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mphy->band_idx);
2891 3232
2892 len = ALIGN(sizeof(*discov) + MT_TXD_SIZE + skb->len, 4);3233 len = ALIGN(sizeof(*discov) + MT_TXD_SIZE + skb->len, 4);
2893 tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len);3234 tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len);
@@ -3742,8 +4083,7 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag) · 848 unmodified lines
3742 4083
3743 if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)4084 if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
3744 req.switch_reason = CH_SWITCH_NORMAL;4085 req.switch_reason = CH_SWITCH_NORMAL;
3745 else if (phy->mt76->offchannel ||4086 else if (phy->mt76->offchannel || !phy->mt76->chanctx)
3746 phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
3747 req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;4087 req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
3748 else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,4088 else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
3749 NL80211_IFTYPE_AP))4089 NL80211_IFTYPE_AP))
@@ -3764,23 +4104,173 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag) · 14 unmodified lines
3764 &req, sizeof(req), true);4104 &req, sizeof(req), true);
3765}4105}
3766 4106
3767static int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev)4107static int
4108mt7996_mcu_get_cal_free_data(struct mt7996_dev *dev)
4109{
4110#define MT_EE_7977BN_OFFSET (0x1200 - 0x500)
4111 struct cal_free_data {
4112 u16 adie_offs;
4113 u16 eep_offs;
4114 };
4115 static const struct cal_free_data cal_7975[] = {
4116 { 0x5cd, 0x451 }, { 0x5cf, 0x453 }, { 0x5d1, 0x455 },
4117 { 0x5d3, 0x457 }, { 0x6c0, 0x44c }, { 0x6c1, 0x44d },
4118 { 0x6c2, 0x44e }, { 0x6c3, 0x44f }, { 0x7a1, 0xba1 },
4119 { 0x7a6, 0xba6 }, { 0x7a8, 0xba8 }, { 0x7aa, 0xbaa },
4120 };
4121 static const struct cal_free_data cal_7976[] = {
4122 { 0x4c, 0x44c }, { 0x4d, 0x44d }, { 0x4e, 0x44e },
4123 { 0x4f, 0x44f }, { 0x50, 0x450 }, { 0x51, 0x451 },
4124 { 0x53, 0x453 }, { 0x55, 0x455 }, { 0x57, 0x457 },
4125 { 0x59, 0x459 }, { 0x70, 0x470 }, { 0x71, 0x471 },
4126 { 0x790, 0xb90 }, { 0x791, 0xb91 }, { 0x794, 0xb94 },
4127 { 0x795, 0xb95 }, { 0x7a6, 0xba6 }, { 0x7a8, 0xba8 },
4128 { 0x7aa, 0xbaa },
4129 };
4130 static const struct cal_free_data cal_7977[] = {
4131 { 0x4c, 0x124c }, { 0x4d, 0x124d }, { 0x4e, 0x124e },
4132 { 0x4f, 0x124f }, { 0x50, 0x1250 }, { 0x51, 0x1251 },
4133 { 0x53, 0x1253 }, { 0x55, 0x1255 }, { 0x57, 0x1257 },
4134 { 0x59, 0x1259 }, { 0x69, 0x1269 }, { 0x6a, 0x126a },
4135 { 0x7a, 0x127a }, { 0x7b, 0x127b }, { 0x7c, 0x127c },
4136 { 0x7d, 0x127d }, { 0x7e, 0x127e },
4137 };
4138 static const struct cal_free_data cal_7978[] = {
4139 { 0x91, 0xb91 }, { 0x95, 0xb95 }, { 0x100, 0x480 },
4140 { 0x102, 0x482 }, { 0x104, 0x484 }, { 0x106, 0x486 },
4141 { 0x107, 0x487 }, { 0x108, 0x488 }, { 0x109, 0x489 },
4142 { 0x10a, 0x48a }, { 0x10b, 0x48b }, { 0x10c, 0x48c },
4143 { 0x10e, 0x48e }, { 0x110, 0x490 },
4144 };
4145 static const struct cal_free_data cal_7979[] = {
4146 { 0x4c, 0x124c }, { 0x4d, 0x124d }, { 0x4e, 0x124e },
4147 { 0x4f, 0x124f }, { 0x50, 0x1250 }, { 0x51, 0x1251 },
4148 { 0x53, 0x1253 }, { 0x55, 0x1255 }, { 0x57, 0x1257 },
4149 { 0x59, 0x1259 }, { 0x69, 0x1269 }, { 0x6a, 0x126a },
4150 { 0x7a, 0x127a }, { 0x7b, 0x127b }, { 0x7c, 0x127c },
4151 { 0x7e, 0x127e }, { 0x80, 0x1280 },
4152 };
4153 const struct cal_free_data *cal_arr[__MT_MAX_BAND];
4154 u16 cal_arr_len[__MT_MAX_BAND] = {};
4155 u8 *eeprom = (u8 *)dev->mt76.eeprom.data;
4156 int band, i, ret;
4157
4158#define CAL_ARR(_band, _adie) do { \
4159 cal_arr[_band] = cal_##_adie; \
4160 cal_arr_len[_band] = ARRAY_SIZE(cal_##_adie); \
4161 } while (0)
4162
4163 switch (mt76_chip(&dev->mt76)) {
4164 case MT7996_DEVICE_ID:
4165 /* adie 0 */
4166 if (dev->var.fem == MT7996_FEM_INT &&
4167 dev->var.type != MT7996_VAR_TYPE_233)
4168 CAL_ARR(0, 7975);
4169 else
4170 CAL_ARR(0, 7976);
4171
4172 /* adie 1 */
4173 if (dev->var.type == MT7996_VAR_TYPE_444)
4174 CAL_ARR(1, 7977);
4175
4176 /* adie 2 */
4177 CAL_ARR(2, 7977);
4178 break;
4179 case MT7992_DEVICE_ID:
4180 /* adie 0 */
4181 if (dev->var.type == MT7992_VAR_TYPE_44 &&
4182 dev->var.fem != MT7996_FEM_EXT)
4183 CAL_ARR(0, 7975);
4184 else if (dev->var.type == MT7992_VAR_TYPE_24)
4185 CAL_ARR(0, 7978);
4186 else
4187 CAL_ARR(0, 7976);
4188
4189 /* adie 1 */
4190 if (dev->var.type == MT7992_VAR_TYPE_44 &&
4191 dev->var.fem != MT7996_FEM_INT)
4192 CAL_ARR(1, 7977);
4193 else if (dev->var.type != MT7992_VAR_TYPE_23)
4194 CAL_ARR(1, 7979);
4195 break;
4196 case MT7990_DEVICE_ID:
4197 /* adie 0 */
4198 CAL_ARR(0, 7976);
4199 break;
4200 default:
4201 return -EINVAL;
4202 }
4203
4204 for (band = 0; band < __MT_MAX_BAND; band++) {
4205 u8 buf[MT7996_EEPROM_BLOCK_SIZE];
4206 const struct cal_free_data *cal;
4207 u16 prev_block_idx = -1;
4208 u16 adie_base;
4209
4210 if (!cal_arr_len[band])
4211 continue;
4212
4213 if (band == MT_BAND0)
4214 adie_base = MT7996_EFUSE_BASE_OFFS_ADIE0;
4215 else if (band == MT_BAND1 && is_mt7992(&dev->mt76))
4216 adie_base = MT7992_EFUSE_BASE_OFFS_ADIE1;
4217 else if (band == MT_BAND1)
4218 adie_base = MT7996_EFUSE_BASE_OFFS_ADIE1;
4219 else
4220 adie_base = MT7996_EFUSE_BASE_OFFS_ADIE2;
4221
4222 cal = cal_arr[band];
4223 for (i = 0; i < cal_arr_len[band]; i++) {
4224 u16 adie_offset = cal[i].adie_offs + adie_base;
4225 u16 eep_offset = cal[i].eep_offs;
4226 u16 block_idx = adie_offset / MT7996_EEPROM_BLOCK_SIZE;
4227 u16 offset = adie_offset % MT7996_EEPROM_BLOCK_SIZE;
4228
4229 if (is_mt7996(&dev->mt76) && band == MT_BAND1 &&
4230 dev->var.type == MT7996_VAR_TYPE_444)
4231 eep_offset -= MT_EE_7977BN_OFFSET;
4232
4233 if (prev_block_idx != block_idx) {
4234 memset(buf, 0, sizeof(buf));
4235 ret = mt7996_mcu_get_eeprom(dev, adie_offset, buf,
4236 MT7996_EEPROM_BLOCK_SIZE,
4237 EEPROM_MODE_EFUSE);
4238 if (ret) {
4239 if (ret != -EINVAL)
4240 return ret;
4241 prev_block_idx = -1;
4242 continue;
4243 }
4244 }
4245 eeprom[eep_offset] = buf[offset];
4246 prev_block_idx = block_idx;
4247 }
4248 }
4249
4250 return 0;
4251}
4252
4253int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
3768{4254{
3769#define MAX_PAGE_IDX_MASK GENMASK(7, 5)4255#define MAX_PAGE_IDX_MASK GENMASK(7, 5)
3770#define PAGE_IDX_MASK GENMASK(4, 2)4256#define PAGE_IDX_MASK GENMASK(4, 2)
3771#define PER_PAGE_SIZE 0x4004257#define PER_PAGE_SIZE 0x400
3772 struct mt7996_mcu_eeprom req = {4258 struct mt7996_mcu_eeprom_update req = {
3773 .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),4259 .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),
3774 .buffer_mode = EE_MODE_BUFFER4260 .buffer_mode = EE_MODE_BUFFER
3775 };4261 };
3776 u16 eeprom_size = MT7996_EEPROM_SIZE;4262 u16 eeprom_size = MT7996_EEPROM_SIZE;
3777 u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE);4263 u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE);
3778 u8 *eep = (u8 *)dev->mt76.eeprom.data;4264 u8 *eep = (u8 *)dev->mt76.eeprom.data;
3779 int eep_len, i;4265 int ret, eep_len, i;
4266
4267 ret = mt7996_mcu_get_cal_free_data(dev);
4268 if (ret)
4269 return ret;
3780 4270
3781 for (i = 0; i < total; i++, eep += eep_len) {4271 for (i = 0; i < total; i++, eep += eep_len) {
3782 struct sk_buff *skb;4272 struct sk_buff *skb;
3783 int ret, msg_len;4273 int msg_len;
3784 4274
3785 if (i == total - 1 && !!(eeprom_size % PER_PAGE_SIZE))4275 if (i == total - 1 && !!(eeprom_size % PER_PAGE_SIZE))
3786 eep_len = eeprom_size % PER_PAGE_SIZE;4276 eep_len = eeprom_size % PER_PAGE_SIZE;
@@ -3809,59 +4299,66 @@ static int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev) · 22 unmodified lines
3809 return 0;4299 return 0;
3810}4300}
3811 4301
3812int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)4302int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
3813{4303 enum mt7996_eeprom_mode mode)
3814 struct mt7996_mcu_eeprom req = {
3815 .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),
3816 .len = cpu_to_le16(sizeof(req) - 4),
3817 .buffer_mode = EE_MODE_EFUSE,
3818 .format = EE_FORMAT_WHOLE
3819 };
3820
3821 if (dev->flash_mode)
3822 return mt7996_mcu_set_eeprom_flash(dev);
3823
3824 return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(EFUSE_CTRL),
3825 &req, sizeof(req), true);
3826}
3827
3828int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len)
3829{4304{
3830 struct {4305 struct mt7996_mcu_eeprom_access req = {
3831 u8 _rsv[4];4306 .info.len = cpu_to_le16(sizeof(req) - 4),
3832
3833 __le16 tag;
3834 __le16 len;
3835 __le32 addr;
3836 __le32 valid;
3837 u8 data[16];
3838 } __packed req = {
3839 .tag = cpu_to_le16(UNI_EFUSE_ACCESS),
3840 .len = cpu_to_le16(sizeof(req) - 4),
3841 .addr = cpu_to_le32(round_down(offset,
3842 MT7996_EEPROM_BLOCK_SIZE)),
3843 };4307 };
4308 struct mt7996_mcu_eeprom_access_event *event;
3844 struct sk_buff *skb;4309 struct sk_buff *skb;
3845 bool valid;4310 int ret, cmd;
3846 int ret;4311 u32 addr;
4312
4313 switch (mode) {
4314 case EEPROM_MODE_EFUSE:
4315 addr = round_down(offset, MT7996_EEPROM_BLOCK_SIZE);
4316 cmd = MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL);
4317 req.info.tag = cpu_to_le16(UNI_EFUSE_ACCESS);
4318 break;
4319 case EEPROM_MODE_EXT:
4320 addr = round_down(offset, MT7996_EXT_EEPROM_BLOCK_SIZE);
4321 cmd = MCU_WM_UNI_CMD_QUERY(EXT_EEPROM_CTRL);
4322 req.info.tag = cpu_to_le16(UNI_EXT_EEPROM_ACCESS);
4323 req.eeprom.ext_eeprom.data_len = cpu_to_le32(buf_len);
4324 break;
4325 default:
4326 return -EINVAL;
4327 }
3847 4328
3848 ret = mt76_mcu_send_and_get_msg(&dev->mt76,4329 req.info.addr = cpu_to_le32(addr);
3849 MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL),4330 ret = mt76_mcu_send_and_get_msg(&dev->mt76, cmd, &req, sizeof(req),
3850 &req, sizeof(req), true, &skb);4331 true, &skb);
3851 if (ret)4332 if (ret)
3852 return ret;4333 return ret;
3853 4334
3854 valid = le32_to_cpu(*(__le32 *)(skb->data + 16));4335 event = (struct mt7996_mcu_eeprom_access_event *)skb->data;
3855 if (valid) {4336 if (event->valid) {
3856 u32 addr = le32_to_cpu(*(__le32 *)(skb->data + 12));4337 u32 ret_len = le32_to_cpu(event->eeprom.ext_eeprom.data_len);
4338
4339 addr = le32_to_cpu(event->addr);
3857 4340
3858 if (!buf)4341 if (!buf)
3859 buf = (u8 *)dev->mt76.eeprom.data + addr;4342 buf = (u8 *)dev->mt76.eeprom.data + addr;
3860 if (!buf_len || buf_len > MT7996_EEPROM_BLOCK_SIZE)
3861 buf_len = MT7996_EEPROM_BLOCK_SIZE;
3862 4343
3863 skb_pull(skb, 48);4344 switch (mode) {
3864 memcpy(buf, skb->data, buf_len);4345 case EEPROM_MODE_EFUSE:
4346 if (!buf_len || buf_len > MT7996_EEPROM_BLOCK_SIZE)
4347 buf_len = MT7996_EEPROM_BLOCK_SIZE;
4348
4349 memcpy(buf, event->eeprom.efuse, buf_len);
4350 break;
4351 case EEPROM_MODE_EXT:
4352 if (!buf_len || buf_len > MT7996_EXT_EEPROM_BLOCK_SIZE)
4353 buf_len = MT7996_EXT_EEPROM_BLOCK_SIZE;
4354
4355 memcpy(buf, event->eeprom.ext_eeprom.data,
4356 ret_len < buf_len ? ret_len : buf_len);
4357 break;
4358 default:
4359 ret = -EINVAL;
4360 break;
4361 }
3865 } else {4362 } else {
3866 ret = -EINVAL;4363 ret = -EINVAL;
3867 }4364 }
@@ -3871,7 +4368,7 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_l · 3 unmodified lines
3871 return ret;4368 return ret;
3872}4369}
3873 4370
3874int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)4371int mt7996_mcu_get_efuse_free_block(struct mt7996_dev *dev, u8 *block_num)
3875{4372{
3876 struct {4373 struct {
3877 u8 _rsv[4];4374 u8 _rsv[4];
@@ -3903,7 +4400,6 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num) · 25 unmodified lines
3903 4400
3904int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)4401int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)
3905{4402{
3906#define NIC_CAP 3
3907#define UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION 0x214403#define UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION 0x21
3908 struct {4404 struct {
3909 u8 _rsv[4];4405 u8 _rsv[4];
@@ -3911,7 +4407,7 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap) · 1 unmodified line
3911 __le16 tag;4407 __le16 tag;
3912 __le16 len;4408 __le16 len;
3913 } __packed req = {4409 } __packed req = {
3914 .tag = cpu_to_le16(NIC_CAP),4410 .tag = cpu_to_le16(UNI_CHIP_CONFIG_NIC_CAPA),
3915 .len = cpu_to_le16(sizeof(req) - 4),4411 .len = cpu_to_le16(sizeof(req) - 4),
3916 };4412 };
3917 struct sk_buff *skb;4413 struct sk_buff *skb;
@@ -4559,6 +5055,35 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable) · 641 unmodified lines
4559 &req, sizeof(req), true);5055 &req, sizeof(req), true);
4560}5056}
4561 5057
5058int mt7996_mcu_rdd_resume_tx(struct mt7996_phy *phy)
5059{
5060 struct {
5061 u8 band_idx;
5062 u8 _rsv[3];
5063
5064 __le16 tag;
5065 __le16 len;
5066 u8 mac_enable;
5067 u8 _rsv2[3];
5068 } __packed req = {
5069 .band_idx = phy->mt76->band_idx,
5070 .tag = cpu_to_le16(UNI_BAND_CONFIG_MAC_ENABLE_CTRL),
5071 .len = cpu_to_le16(sizeof(req) - 4),
5072 .mac_enable = 2,
5073 };
5074 int ret;
5075
5076 if (!phy->rdd_tx_paused)
5077 return 0;
5078
5079 ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
5080 &req, sizeof(req), true);
5081 if (!ret)
5082 phy->rdd_tx_paused = false;
5083
5084 return ret;
5085}
5086
4562int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val)5087int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val)
4563{5088{
4564 struct {5089 struct {
@@ -4889,3 +5414,25 @@ int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode) · 324 unmodified lines
4889 return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(CP_SUPPORT),5414 return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(CP_SUPPORT),
4890 &cp_mode, sizeof(cp_mode), true);5415 &cp_mode, sizeof(cp_mode), true);
4891}5416}
5417
5418int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev)
5419{
5420#define DUP_WTBL_NUM 80
5421 struct {
5422 u8 _rsv[4];
5423
5424 __le16 tag;
5425 __le16 len;
5426 __le16 base;
5427 __le16 num;
5428 u8 _rsv2[4];
5429 } __packed req = {
5430 .tag = cpu_to_le16(UNI_CHIP_CONFIG_DUP_WTBL),
5431 .len = cpu_to_le16(sizeof(req) - 4),
5432 .base = cpu_to_le16(MT7996_WTBL_STA - DUP_WTBL_NUM + 1),
5433 .num = cpu_to_le16(DUP_WTBL_NUM),
5434 };
5435
5436 return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(CHIP_CONFIG), &req,
5437 sizeof(req), true);
5438}
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h+103−9
@@ -25,8 +25,8 @@ struct mt7996_mcu_rxd { · 24 unmodified lines
25};25};
26 26
27struct mt7996_mcu_uni_event {27struct mt7996_mcu_uni_event {
28 u8 cid;28 __le16 cid;
29 u8 __rsv[3];29 u8 __rsv[2];
30 __le32 status; /* 0: success, others: fail */30 __le32 status; /* 0: success, others: fail */
31} __packed;31} __packed;
32 32
@@ -52,12 +52,10 @@ struct mt7996_mcu_thermal_enable { · 19 unmodified lines
52 u8 rsv[2];52 u8 rsv[2];
53} __packed;53} __packed;
54 54
55struct mt7996_mcu_csa_notify {55struct mt7996_mcu_countdown_notify {
56 struct mt7996_mcu_rxd rxd;
57
58 u8 omac_idx;56 u8 omac_idx;
59 u8 csa_count;57 u8 count;
60 u8 band_idx;58 u8 csa_failure_reason; /* 0: success, 1: beacon disabled */
61 u8 rsv;59 u8 rsv;
62} __packed;60} __packed;
63 61
@@ -147,7 +145,7 @@ struct mt7996_mcu_background_chain_ctrl { · 83 unmodified lines
147 u8 rsv[2];145 u8 rsv[2];
148} __packed;146} __packed;
149 147
150struct mt7996_mcu_eeprom {148struct mt7996_mcu_eeprom_update {
151 u8 _rsv[4];149 u8 _rsv[4];
152 150
153 __le16 tag;151 __le16 tag;
@@ -157,6 +155,43 @@ struct mt7996_mcu_eeprom { · 3 unmodified lines
157 __le16 buf_len;155 __le16 buf_len;
158} __packed;156} __packed;
159 157
158union eeprom_data {
159 struct {
160 __le32 data_len;
161 DECLARE_FLEX_ARRAY(u8, data);
162 } ext_eeprom;
163 DECLARE_FLEX_ARRAY(u8, efuse);
164} __packed;
165
166struct mt7996_mcu_eeprom_info {
167 u8 _rsv[4];
168
169 __le16 tag;
170 __le16 len;
171 __le32 addr;
172 __le32 valid;
173} __packed;
174
175struct mt7996_mcu_eeprom_access {
176 struct mt7996_mcu_eeprom_info info;
177 union eeprom_data eeprom;
178} __packed;
179
180struct mt7996_mcu_eeprom_access_event {
181 u8 _rsv[4];
182
183 __le16 tag;
184 __le16 len;
185 __le32 version;
186 __le32 addr;
187 __le32 valid;
188 __le32 size;
189 __le32 magic_no;
190 __le32 type;
191 __le32 rsv[4];
192 union eeprom_data eeprom;
193} __packed;
194
160struct mt7996_mcu_phy_rx_info {195struct mt7996_mcu_phy_rx_info {
161 u8 category;196 u8 category;
162 u8 rate;197 u8 rate;
@@ -414,7 +449,16 @@ struct bss_bcn_cntdwn_tlv { · 251 unmodified lines
414 __le16 tag;449 __le16 tag;
415 __le16 len;450 __le16 len;
416 u8 cnt;451 u8 cnt;
417 u8 rsv[3];452 union {
453 struct {
454 bool static_pp;
455 bool abort;
456 } csa;
457 struct {
458 bool abort;
459 } cca;
460 };
461 u8 rsv;
418} __packed;462} __packed;
419 463
420struct bss_bcn_mbss_tlv {464struct bss_bcn_mbss_tlv {
@@ -474,6 +518,24 @@ struct bss_mld_tlv { · 53 unmodified lines
474 u8 __rsv[2];518 u8 __rsv[2];
475} __packed;519} __packed;
476 520
521struct bss_prot_tlv {
522 __le16 tag;
523 __le16 len;
524 __le32 prot_mode;
525} __packed;
526
527struct bss_mld_link_op_tlv {
528 __le16 tag;
529 __le16 len;
530 u8 group_mld_id;
531 u8 own_mld_id;
532 u8 mac_addr[ETH_ALEN];
533 u8 remap_idx;
534 u8 link_operation;
535 u8 link_id;
536 u8 rsv[2];
537} __packed;
538
477struct sta_rec_ht_uni {539struct sta_rec_ht_uni {
478 __le16 tag;540 __le16 tag;
479 __le16 len;541 __le16 len;
@@ -647,6 +709,28 @@ struct mld_setup_link { · 167 unmodified lines
647 u8 __rsv;709 u8 __rsv;
648} __packed;710} __packed;
649 711
712struct mld_req_hdr {
713 u8 ver;
714 u8 mld_addr[ETH_ALEN];
715 u8 mld_idx;
716 u8 flag;
717 u8 rsv[3];
718 u8 buf[];
719} __packed;
720
721struct mld_reconf_stop_link {
722 __le16 tag;
723 __le16 len;
724 __le16 link_bitmap;
725 u8 rsv[2];
726 u8 bss_idx[16];
727} __packed;
728
729enum {
730 UNI_CMD_MLD_RECONF_AP_REM_TIMER = 0x03,
731 UNI_CMD_MLD_RECONF_STOP_LINK = 0x04,
732};
733
650struct hdr_trans_en {734struct hdr_trans_en {
651 __le16 tag;735 __le16 tag;
652 __le16 len;736 __le16 len;
@@ -791,6 +875,11 @@ enum { · 138 unmodified lines
791 UNI_CHANNEL_RX_PATH,875 UNI_CHANNEL_RX_PATH,
792};876};
793 877
878enum {
879 UNI_CHIP_CONFIG_NIC_CAPA = 3,
880 UNI_CHIP_CONFIG_DUP_WTBL = 4,
881};
882
794#define MT7996_BSS_UPDATE_MAX_SIZE (sizeof(struct bss_req_hdr) + \883#define MT7996_BSS_UPDATE_MAX_SIZE (sizeof(struct bss_req_hdr) + \
795 sizeof(struct mt76_connac_bss_basic_tlv) + \884 sizeof(struct mt76_connac_bss_basic_tlv) + \
796 sizeof(struct bss_rlm_tlv) + \885 sizeof(struct bss_rlm_tlv) + \
@@ -837,6 +926,7 @@ enum { · 40 unmodified lines
837enum {926enum {
838 UNI_BAND_CONFIG_RADIO_ENABLE,927 UNI_BAND_CONFIG_RADIO_ENABLE,
839 UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,928 UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
929 UNI_BAND_CONFIG_MAC_ENABLE_CTRL = 0x0c,
840};930};
841 931
842enum {932enum {
@@ -856,6 +946,10 @@ enum { · 13 unmodified lines
856 UNI_EFUSE_BUFFER_RD,946 UNI_EFUSE_BUFFER_RD,
857};947};
858 948
949enum {
950 UNI_EXT_EEPROM_ACCESS = 1,
951};
952
859enum {953enum {
860 UNI_VOW_DRR_CTRL,954 UNI_VOW_DRR_CTRL,
861 UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,955 UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h+63−7
@@ -29,6 +29,10 @@ · 28 unmodified lines
29#define MT7996_RX_RING_SIZE 153629#define MT7996_RX_RING_SIZE 1536
30#define MT7996_RX_MCU_RING_SIZE 51230#define MT7996_RX_MCU_RING_SIZE 512
31#define MT7996_RX_MCU_RING_SIZE_WA 102431#define MT7996_RX_MCU_RING_SIZE_WA 1024
32#define MT7996_NPU_TX_RING_SIZE 1024
33#define MT7996_NPU_RX_RING_SIZE 1024
34#define MT7996_NPU_TXD_SIZE 3
35
32/* scatter-gather of mcu event is not supported in connac3 */36/* scatter-gather of mcu event is not supported in connac3 */
33#define MT7996_RX_MCU_BUF_SIZE (2048 + \37#define MT7996_RX_MCU_BUF_SIZE (2048 + \
34 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))38 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
@@ -60,6 +64,11 @@ · 25 unmodified lines
60#define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"64#define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"
61#define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"65#define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"
62 66
67#define MT7992_FIRMWARE_WA_24 "mediatek/mt7996/mt7992_wa_24.bin"
68#define MT7992_FIRMWARE_WM_24 "mediatek/mt7996/mt7992_wm_24.bin"
69#define MT7992_FIRMWARE_DSP_24 "mediatek/mt7996/mt7992_dsp_24.bin"
70#define MT7992_ROM_PATCH_24 "mediatek/mt7996/mt7992_rom_patch_24.bin"
71
63#define MT7990_FIRMWARE_WA ""72#define MT7990_FIRMWARE_WA ""
64#define MT7990_FIRMWARE_WM "mediatek/mt7996/mt7990_wm.bin"73#define MT7990_FIRMWARE_WM "mediatek/mt7996/mt7990_wm.bin"
65#define MT7990_FIRMWARE_DSP ""74#define MT7990_FIRMWARE_DSP ""
@@ -75,12 +84,14 @@ · 9 unmodified lines
75#define MT7992_EEPROM_DEFAULT_MIX "mediatek/mt7996/mt7992_eeprom_2i5e.bin"84#define MT7992_EEPROM_DEFAULT_MIX "mediatek/mt7996/mt7992_eeprom_2i5e.bin"
76#define MT7992_EEPROM_DEFAULT_23 "mediatek/mt7996/mt7992_eeprom_23.bin"85#define MT7992_EEPROM_DEFAULT_23 "mediatek/mt7996/mt7992_eeprom_23.bin"
77#define MT7992_EEPROM_DEFAULT_23_INT "mediatek/mt7996/mt7992_eeprom_23_2i5i.bin"86#define MT7992_EEPROM_DEFAULT_23_INT "mediatek/mt7996/mt7992_eeprom_23_2i5i.bin"
87#define MT7992_EEPROM_DEFAULT_24 "mediatek/mt7996/mt7992_eeprom_24_2i5i.bin"
78 88
79#define MT7990_EEPROM_DEFAULT "mediatek/mt7996/mt7990_eeprom.bin"89#define MT7990_EEPROM_DEFAULT "mediatek/mt7996/mt7990_eeprom.bin"
80#define MT7990_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7990_eeprom_2i5i.bin"90#define MT7990_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7990_eeprom_2i5i.bin"
81 91
82#define MT7996_EEPROM_SIZE 768092#define MT7996_EEPROM_SIZE 7680
83#define MT7996_EEPROM_BLOCK_SIZE 1693#define MT7996_EEPROM_BLOCK_SIZE 16
94#define MT7996_EXT_EEPROM_BLOCK_SIZE 1024
84#define MT7996_TOKEN_SIZE 1638495#define MT7996_TOKEN_SIZE 16384
85#define MT7996_HW_TOKEN_SIZE 819296#define MT7996_HW_TOKEN_SIZE 8192
86 97
@@ -153,6 +164,7 @@ enum mt7996_var_type { · 66 unmodified lines
153enum mt7992_var_type {164enum mt7992_var_type {
154 MT7992_VAR_TYPE_44,165 MT7992_VAR_TYPE_44,
155 MT7992_VAR_TYPE_23,166 MT7992_VAR_TYPE_23,
167 MT7992_VAR_TYPE_24,
156};168};
157 169
158enum mt7990_var_type {170enum mt7990_var_type {
@@ -165,6 +177,18 @@ enum mt7996_fem_type { · 6 unmodified lines
165 MT7996_FEM_MIX,177 MT7996_FEM_MIX,
166};178};
167 179
180enum mt7996_eeprom_mode {
181 EEPROM_MODE_DEFAULT_BIN,
182 EEPROM_MODE_EFUSE,
183 EEPROM_MODE_FLASH,
184 EEPROM_MODE_EXT,
185};
186
187#define MT7996_EFUSE_BASE_OFFS_ADIE0 0x400
188#define MT7996_EFUSE_BASE_OFFS_ADIE1 0x1e00
189#define MT7996_EFUSE_BASE_OFFS_ADIE2 0x1200
190#define MT7992_EFUSE_BASE_OFFS_ADIE1 0x1200
191
168enum mt7996_txq_id {192enum mt7996_txq_id {
169 MT7996_TXQ_FWDL = 16,193 MT7996_TXQ_FWDL = 16,
170 MT7996_TXQ_MCU_WM,194 MT7996_TXQ_MCU_WM,
@@ -252,8 +276,6 @@ struct mt7996_vif_link { · 81 unmodified lines
252 struct mt76_vif_link mt76; /* must be first */276 struct mt76_vif_link mt76; /* must be first */
253 277
254 struct mt7996_sta_link msta_link;278 struct mt7996_sta_link msta_link;
255 struct mt7996_phy *phy;
256
257 struct cfg80211_bitrate_mask bitrate_mask;279 struct cfg80211_bitrate_mask bitrate_mask;
258 280
259 u8 mld_idx;281 u8 mld_idx;
@@ -377,6 +399,7 @@ struct mt7996_phy { · 117 unmodified lines
377 399
378 bool has_aux_rx;400 bool has_aux_rx;
379 bool counter_reset;401 bool counter_reset;
402 bool rdd_tx_paused;
380};403};
381 404
382struct mt7996_dev {405struct mt7996_dev {
@@ -436,7 +459,7 @@ struct mt7996_dev { · 53 unmodified lines
436 459
437 u32 hw_pattern;460 u32 hw_pattern;
438 461
439 bool flash_mode:1;462 u8 eeprom_mode;
440 bool has_eht:1;463 bool has_eht:1;
441 464
442 struct {465 struct {
@@ -473,6 +496,8 @@ struct mt7996_dev { · 30 unmodified lines
473 struct list_head page_map[MT7996_RRO_MSDU_PG_HASH_SIZE];496 struct list_head page_map[MT7996_RRO_MSDU_PG_HASH_SIZE];
474 } wed_rro;497 } wed_rro;
475 498
499 dma_addr_t npu_txd_addr[2 * MT7996_NPU_TXD_SIZE];
500
476 bool ibf;501 bool ibf;
477 u8 fw_debug_wm;502 u8 fw_debug_wm;
478 u8 fw_debug_wa;503 u8 fw_debug_wa;
@@ -669,6 +694,8 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif, · 190 unmodified lines
669 struct ieee80211_bss_conf *link_conf,694 struct ieee80211_bss_conf *link_conf,
670 struct mt76_vif_link *mlink,695 struct mt76_vif_link *mlink,
671 struct mt7996_sta_link *msta_link, int enable);696 struct mt7996_sta_link *msta_link, int enable);
697int mt7996_mcu_update_bss_rfch(struct mt7996_phy *phy,
698 struct mt7996_vif_link *link);
672int mt7996_mcu_add_sta(struct mt7996_dev *dev,699int mt7996_mcu_add_sta(struct mt7996_dev *dev,
673 struct ieee80211_bss_conf *link_conf,700 struct ieee80211_bss_conf *link_conf,
674 struct ieee80211_link_sta *link_sta,701 struct ieee80211_link_sta *link_sta,
@@ -678,6 +705,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, · 3 unmodified lines
678int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,705int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
679 struct mt7996_vif_link *link,706 struct mt7996_vif_link *link,
680 struct mt7996_sta_link *msta_link);707 struct mt7996_sta_link *msta_link);
708void mt7996_mcu_update_sta_rec_bw(void *data, struct ieee80211_sta *sta);
681int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,709int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
682 struct ieee80211_ampdu_params *params,710 struct ieee80211_ampdu_params *params,
683 struct ieee80211_vif *vif, bool enable);711 struct ieee80211_vif *vif, bool enable);
@@ -707,8 +735,9 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, · 23 unmodified lines
707int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,735int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
708 void *data, u8 link_id, u32 field);736 void *data, u8 link_id, u32 field);
709int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);737int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
710int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);738int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
711int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);739 enum mt7996_eeprom_mode mode);
740int mt7996_mcu_get_efuse_free_block(struct mt7996_dev *dev, u8 *block_num);
712int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap);741int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap);
713int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band);742int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band);
714int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action);743int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action);
@@ -719,6 +748,8 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index, · 4 unmodified lines
719 const struct mt7996_dfs_pattern *pattern);748 const struct mt7996_dfs_pattern *pattern);
720int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);749int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
721int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);750int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
751int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *link,
752 u8 ht_mode, bool use_cts_prot);
722int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,753int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
723 struct ieee80211_bss_conf *link_conf);754 struct ieee80211_bss_conf *link_conf);
724int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);755int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
@@ -726,6 +757,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy); · 1 unmodified line
726int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);757int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
727int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);758int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
728int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);759int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
760int mt7996_mcu_rdd_resume_tx(struct mt7996_phy *phy);
729int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val);761int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val);
730int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,762int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
731 struct cfg80211_chan_def *chandef);763 struct cfg80211_chan_def *chandef);
@@ -743,6 +775,13 @@ void mt7996_mcu_exit(struct mt7996_dev *dev); · 11 unmodified lines
743int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);775int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
744int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);776int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
745int mt7996_mcu_set_sniffer_mode(struct mt7996_phy *phy, bool enabled);777int mt7996_mcu_set_sniffer_mode(struct mt7996_phy *phy, bool enabled);
778int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev);
779int mt7996_mcu_mld_reconf_stop_link(struct mt7996_dev *dev,
780 struct ieee80211_vif *vif,
781 u16 removed_links);
782int mt7996_mcu_mld_link_oper(struct mt7996_dev *dev,
783 struct ieee80211_bss_conf *link_conf,
784 struct mt7996_vif_link *link, bool add);
746 785
747static inline bool mt7996_has_hwrro(struct mt7996_dev *dev)786static inline bool mt7996_has_hwrro(struct mt7996_dev *dev)
748{787{
@@ -802,6 +841,11 @@ static inline bool mt7996_has_wa(struct mt7996_dev *dev) · 53 unmodified lines
802 return !is_mt7990(&dev->mt76);841 return !is_mt7990(&dev->mt76);
803}842}
804 843
844static inline bool mt7996_has_ext_eeprom(struct mt7996_dev *dev)
845{
846 return !is_mt7996(&dev->mt76);
847}
848
805void mt7996_mac_init(struct mt7996_dev *dev);849void mt7996_mac_init(struct mt7996_dev *dev);
806u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);850u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
807bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);851bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
@@ -823,8 +867,9 @@ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, · 15 unmodified lines
823 struct mt7996_vif_link *link,867 struct mt7996_vif_link *link,
824 struct mt7996_sta_link *msta_link,868 struct mt7996_sta_link *msta_link,
825 u8 flowid);869 u8 flowid);
826void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,870void mt7996_mac_sta_remove_link(struct mt7996_dev *dev,
827 struct mt7996_sta_link *msta_link);871 struct ieee80211_sta *sta,
872 unsigned int link_id, bool flush);
828void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,873void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
829 struct ieee80211_sta *sta,874 struct ieee80211_sta *sta,
830 struct ieee80211_twt_setup *twt);875 struct ieee80211_twt_setup *twt);
@@ -861,6 +906,10 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev, · 30 unmodified lines
861 struct mt7996_vif_link *link,906 struct mt7996_vif_link *link,
862 struct mt7996_sta_link *msta_link);907 struct mt7996_sta_link *msta_link);
863int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);908int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
909int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev,
910 struct ieee80211_vif *vif,
911 struct ieee80211_sta *sta,
912 struct ieee80211_eml_params *eml_params);
864#ifdef CONFIG_MAC80211_DEBUGFS913#ifdef CONFIG_MAC80211_DEBUGFS
865void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,914void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
866 struct ieee80211_sta *sta, struct dentry *dir);915 struct ieee80211_sta *sta, struct dentry *dir);
@@ -877,12 +926,19 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir); · 10 unmodified lines
877#endif926#endif
878 927
879int mt7996_dma_rro_init(struct mt7996_dev *dev);928int mt7996_dma_rro_init(struct mt7996_dev *dev);
929void mt7996_dma_rro_start(struct mt7996_dev *dev);
880 930
881#ifdef CONFIG_MT7996_NPU931#ifdef CONFIG_MT7996_NPU
932int __mt7996_npu_hw_init(struct mt7996_dev *dev);
882int mt7996_npu_hw_init(struct mt7996_dev *dev);933int mt7996_npu_hw_init(struct mt7996_dev *dev);
883int mt7996_npu_hw_stop(struct mt7996_dev *dev);934int mt7996_npu_hw_stop(struct mt7996_dev *dev);
884int mt7996_npu_rx_queues_init(struct mt7996_dev *dev);935int mt7996_npu_rx_queues_init(struct mt7996_dev *dev);
885#else936#else
937static inline int __mt7996_npu_hw_init(struct mt7996_dev *dev)
938{
939 return 0;
940}
941
886static inline int mt7996_npu_hw_init(struct mt7996_dev *dev)942static inline int mt7996_npu_hw_init(struct mt7996_dev *dev)
887{943{
888 return 0;944 return 0;
drivers/net/wireless/mediatek/mt76/mt7996/npu.c+372−93
@@ -8,55 +8,20 @@ · 7 unmodified lines
8 8
9#include "mt7996.h"9#include "mt7996.h"
10 10
11static int mt7996_npu_offload_init(struct mt7996_dev *dev,11static int mt7992_npu_txrx_offload_init(struct mt7996_dev *dev,
12 struct airoha_npu *npu)12 struct airoha_npu *npu)
13{13{
14 u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
14 phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;15 phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
15 u32 val, hif1_ofs = 0, dma_addr;16 u32 dma_addr;
16 int i, err;17 int i, err;
17 18
18 err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_NPU_VERSION,
19 &val, GFP_KERNEL);
20 if (err) {
21 dev_warn(dev->mt76.dev, "failed getting NPU fw version\n");
22 return err;
23 }
24
25 dev_info(dev->mt76.dev, "NPU version: %0d.%d\n",
26 (val >> 16) & 0xffff, val & 0xffff);
27
28 err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE,
29 dev->mt76.mmio.npu_type, GFP_KERNEL);
30 if (err) {
31 dev_warn(dev->mt76.dev,
32 "failed setting NPU wlan PCIe port type\n");
33 return err;
34 }
35
36 if (dev->hif2)
37 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
38
39 for (i = MT_BAND0; i < MT_BAND2; i++) {19 for (i = MT_BAND0; i < MT_BAND2; i++) {
40 dma_addr = phy_addr;
41 if (i)
42 dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + 0x90 +
43 hif1_ofs;
44 else
45 dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0) + 0x80;
46
47 err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
48 dma_addr, GFP_KERNEL);
49 if (err) {
50 dev_warn(dev->mt76.dev,
51 "failed setting NPU wlan PCIe desc addr\n");
52 return err;
53 }
54
55 err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_DESC,20 err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_DESC,
56 MT7996_RX_RING_SIZE, GFP_KERNEL);21 MT7996_RX_RING_SIZE, GFP_KERNEL);
57 if (err) {22 if (err) {
58 dev_warn(dev->mt76.dev,23 dev_warn(dev->mt76.dev,
59 "failed setting NPU wlan PCIe desc size\n");24 "failed setting NPU wlan rx desc size\n");
60 return err;25 return err;
61 }26 }
62 27
@@ -97,10 +62,173 @@ static int mt7996_npu_offload_init(struct mt7996_dev *dev, · 34 unmodified lines
97 phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);62 phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
98 if (err) {63 if (err) {
99 dev_warn(dev->mt76.dev,64 dev_warn(dev->mt76.dev,
100 "failed setting NPU wlan rro_ack_sn desc addr\n");65 "failed setting NPU wlan tx desc addr\n");
66 return err;
67 }
68
69 return 0;
70}
71
72static int mt7996_npu_txrx_offload_init(struct mt7996_dev *dev,
73 struct airoha_npu *npu)
74{
75 u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
76 phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
77 u32 dma_addr;
78 int err;
79
80 /* npu rx rro ring0 */
81 err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_DESC,
82 MT7996_RX_RING_SIZE, GFP_KERNEL);
83 if (err) {
84 dev_warn(dev->mt76.dev,
85 "failed setting NPU wlan rx desc size\n");
86 return err;
87 }
88
89 /* npu rx rro ring1 */
90 err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_DESC,
91 MT7996_NPU_RX_RING_SIZE, GFP_KERNEL);
92 if (err) {
93 dev_warn(dev->mt76.dev,
94 "failed setting NPU wlan rx desc size\n");
95 return err;
96 }
97
98 /* msdu pg 2GHz */
99 dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0) + 0xa0;
100 err = mt76_npu_send_msg(npu, 5, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
101 dma_addr, GFP_KERNEL);
102 if (err) {
103 dev_warn(dev->mt76.dev,
104 "failed setting NPU wlan PCIe desc addr\n");
105 return err;
106 }
107
108 err = mt76_npu_send_msg(npu, 5, WLAN_FUNC_SET_WAIT_DESC,
109 MT7996_NPU_RX_RING_SIZE / 4, GFP_KERNEL);
110 if (err) {
111 dev_warn(dev->mt76.dev,
112 "failed setting NPU wlan rx desc size\n");
113 return err;
114 }
115
116 /* msdu pg 5GHz */
117 dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1) + 0xb0;
118 err = mt76_npu_send_msg(npu, 6, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
119 dma_addr, GFP_KERNEL);
120 if (err) {
121 dev_warn(dev->mt76.dev,
122 "failed setting NPU wlan PCIe desc addr\n");
123 return err;
124 }
125
126 err = mt76_npu_send_msg(npu, 6, WLAN_FUNC_SET_WAIT_DESC,
127 MT7996_NPU_RX_RING_SIZE / 2, GFP_KERNEL);
128 if (err) {
129 dev_warn(dev->mt76.dev,
130 "failed setting NPU wlan rx desc size\n");
131 return err;
132 }
133
134 /* msdu pg 6GHz */
135 dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2) + 0xc0;
136 err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
137 dma_addr, GFP_KERNEL);
138 if (err) {
139 dev_warn(dev->mt76.dev,
140 "failed setting NPU wlan PCIe desc addr\n");
141 return err;
142 }
143
144 err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_DESC,
145 MT7996_NPU_RX_RING_SIZE, GFP_KERNEL);
146 if (err) {
147 dev_warn(dev->mt76.dev,
148 "failed setting NPU wlan rx desc size\n");
149 return err;
150 }
151
152 /* ind cmd ring */
153 err = mt76_npu_send_msg(npu, 8, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
154 phy_addr + MT_RXQ_RRO_IND_RING_BASE,
155 GFP_KERNEL);
156 if (err) {
157 dev_warn(dev->mt76.dev,
158 "failed setting NPU wlan PCIe desc addr\n");
159 return err;
160 }
161
162 err = mt76_npu_send_msg(npu, 8, WLAN_FUNC_SET_WAIT_DESC,
163 MT7996_RX_RING_SIZE, GFP_KERNEL);
164 if (err) {
165 dev_warn(dev->mt76.dev,
166 "failed setting NPU wlan rx desc size\n");
167 return err;
168 }
169
170 err = mt76_npu_send_msg(npu, 3, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
171 phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
172 if (err) {
173 dev_warn(dev->mt76.dev,
174 "failed setting NPU wlan tx desc addr\n");
175 return err;
176 }
177
178 /* npu tx */
179 dma_addr = phy_addr + MT_TXQ_RING_BASE(1) + 0x120;
180 err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
181 dma_addr, GFP_KERNEL);
182 if (err) {
183 dev_warn(dev->mt76.dev,
184 "failed setting NPU wlan tx desc addr\n");
185 return err;
186 }
187
188 dma_addr = phy_addr + MT_TXQ_RING_BASE(0) + 0x150 + hif1_ofs;
189 err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
190 dma_addr, GFP_KERNEL);
191 if (err) {
192 dev_warn(dev->mt76.dev,
193 "failed setting NPU wlan tx desc addr\n");
101 return err;194 return err;
102 }195 }
103 196
197 return 0;
198}
199
200static int mt7996_npu_offload_init(struct mt7996_dev *dev,
201 struct airoha_npu *npu)
202{
203 u32 val;
204 int err;
205
206 err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_NPU_VERSION,
207 &val, GFP_KERNEL);
208 if (err) {
209 dev_warn(dev->mt76.dev, "failed getting NPU fw version\n");
210 return err;
211 }
212
213 dev_info(dev->mt76.dev, "NPU version: %0d.%d\n",
214 (val >> 16) & 0xffff, val & 0xffff);
215
216 err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE,
217 dev->mt76.mmio.npu_type, GFP_KERNEL);
218 if (err) {
219 dev_warn(dev->mt76.dev,
220 "failed setting NPU wlan PCIe port type\n");
221 return err;
222 }
223
224 if (is_mt7996(&dev->mt76))
225 err = mt7996_npu_txrx_offload_init(dev, npu);
226 else
227 err = mt7992_npu_txrx_offload_init(dev, npu);
228
229 if (err)
230 return err;
231
104 err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE,232 err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE,
105 MT7996_HW_TOKEN_SIZE, GFP_KERNEL);233 MT7996_HW_TOKEN_SIZE, GFP_KERNEL);
106 if (err)234 if (err)
@@ -111,7 +239,7 @@ static int mt7996_npu_offload_init(struct mt7996_dev *dev, · 4 unmodified lines
111 return 0;239 return 0;
112}240}
113 241
114static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)242static int mt7992_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
115{243{
116 u32 val;244 u32 val;
117 int err;245 int err;
@@ -120,7 +248,7 @@ static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu) · 2 unmodified lines
120 &val, GFP_KERNEL);248 &val, GFP_KERNEL);
121 if (err) {249 if (err) {
122 dev_warn(dev->mt76.dev,250 dev_warn(dev->mt76.dev,
123 "failed retriving NPU wlan rx ring0 addr\n");251 "failed retrieving NPU wlan rx ring0 addr\n");
124 return err;252 return err;
125 }253 }
126 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);254 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
@@ -129,7 +257,7 @@ static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu) · 2 unmodified lines
129 &val, GFP_KERNEL);257 &val, GFP_KERNEL);
130 if (err) {258 if (err) {
131 dev_warn(dev->mt76.dev,259 dev_warn(dev->mt76.dev,
132 "failed retriving NPU wlan rx ring1 addr\n");260 "failed retrieving NPU wlan rx ring1 addr\n");
133 return err;261 return err;
134 }262 }
135 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1].regs->desc_base);263 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1].regs->desc_base);
@@ -138,7 +266,7 @@ static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu) · 2 unmodified lines
138 &val, GFP_KERNEL);266 &val, GFP_KERNEL);
139 if (err) {267 if (err) {
140 dev_warn(dev->mt76.dev,268 dev_warn(dev->mt76.dev,
141 "failed retriving NPU wlan rxdmad_c ring addr\n");269 "failed retrieving NPU wlan rxdmad_c ring addr\n");
142 return err;270 return err;
143 }271 }
144 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_RXDMAD_C].regs->desc_base);272 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_RXDMAD_C].regs->desc_base);
@@ -146,59 +274,121 @@ static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu) · 1 unmodified line
146 return 0;274 return 0;
147}275}
148 276
277static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
278{
279 u32 val;
280 int err;
281
282 err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
283 &val, GFP_KERNEL);
284 if (err) {
285 dev_warn(dev->mt76.dev,
286 "failed retriving NPU wlan rx ring0 addr\n");
287 return err;
288 }
289 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
290
291 err = mt76_npu_get_msg(npu, 2, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
292 &val, GFP_KERNEL);
293 if (err) {
294 dev_warn(dev->mt76.dev,
295 "failed retriving NPU wlan rx ring2 addr\n");
296 return err;
297 }
298 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2].regs->desc_base);
299
300 /* msdu pg ring */
301 err = mt76_npu_get_msg(npu, 10, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
302 &val, GFP_KERNEL);
303 if (err) {
304 dev_warn(dev->mt76.dev,
305 "failed retriving NPU wlan msdu pg ring addr\n");
306 return err;
307 }
308 writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].regs->desc_base);
309
310 err = mt76_npu_get_msg(npu, 11, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
311 &val, GFP_KERNEL);
312 if (err) {
313 dev_warn(dev->mt76.dev,
314 "failed retriving NPU wlan msdu pg ring addr\n");
315 return err;
316 }
317 writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].regs->desc_base);
318
319 err = mt76_npu_get_msg(npu, 12, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
320 &val, GFP_KERNEL);
321 if (err) {
322 dev_warn(dev->mt76.dev,
323 "failed retriving NPU wlan msdu pg ring addr\n");
324 return err;
325 }
326 writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].regs->desc_base);
327
328 /* ind_cmd ring */
329 err = mt76_npu_get_msg(npu, 8, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
330 &val, GFP_KERNEL);
331 if (err) {
332 dev_warn(dev->mt76.dev,
333 "failed retriving NPU wlan ind_cmd ring addr\n");
334 return err;
335 }
336 writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_IND].regs->desc_base);
337
338 return 0;
339}
340
149static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu)341static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
150{342{
151 int i, err;343 const enum mt76_band_id band_list[] = {
344 MT_BAND0,
345 is_mt7996(&dev->mt76) ? MT_BAND2 : MT_BAND1,
346 };
347 int i, index = 0;
152 348
153 for (i = MT_BAND0; i < MT_BAND2; i++) {349 BUILD_BUG_ON(ARRAY_SIZE(band_list) * 3 !=
154 dma_addr_t dma_addr;350 ARRAY_SIZE(dev->npu_txd_addr));
351
352 for (i = 0; i < ARRAY_SIZE(band_list); i++) {
353 int err, band = band_list[i], phy_id;
155 u32 val;354 u32 val;
156 355
157 err = mt76_npu_get_msg(npu, i + 5,356 err = mt76_npu_get_msg(npu, band + 5,
158 WLAN_FUNC_GET_WAIT_RXDESC_BASE,357 WLAN_FUNC_GET_WAIT_RXDESC_BASE,
159 &val, GFP_KERNEL);358 &val, GFP_KERNEL);
160 if (err) {359 if (err) {
161 dev_warn(dev->mt76.dev,360 dev_warn(dev->mt76.dev,
162 "failed retriving NPU wlan tx ring addr\n");361 "failed retrieving NPU wlan tx ring addr\n");
163 return err;362 return err;
164 }363 }
165 writel(val, &dev->mt76.phys[i]->q_tx[0]->regs->desc_base);
166 364
167 if (!dmam_alloc_coherent(dev->mt76.dma_dev,365 phy_id = is_mt7996(&dev->mt76) ? band == MT_BAND0 ? 1 : 0
168 256 * MT7996_TX_RING_SIZE,366 : band;
169 &dma_addr, GFP_KERNEL))367 writel(val, &dev->mt76.phys[phy_id]->q_tx[0]->regs->desc_base);
170 return -ENOMEM;
171 368
172 err = mt76_npu_send_msg(npu, i,369 err = mt76_npu_send_msg(npu, band,
173 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,370 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
174 dma_addr, GFP_KERNEL);371 dev->npu_txd_addr[index++], GFP_KERNEL);
175 if (err) {372 if (err) {
176 dev_warn(dev->mt76.dev,373 dev_warn(dev->mt76.dev,
177 "failed setting NPU wlan queue buf addr\n");374 "failed setting NPU wlan queue buf addr\n");
178 return err;375 return err;
179 }376 }
180 377
181 if (!dmam_alloc_coherent(dev->mt76.dma_dev,378 err = mt76_npu_send_msg(npu, band + 5,
182 256 * MT7996_TX_RING_SIZE,
183 &dma_addr, GFP_KERNEL))
184 return -ENOMEM;
185
186 err = mt76_npu_send_msg(npu, i + 5,
187 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,379 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
188 dma_addr, GFP_KERNEL);380 dev->npu_txd_addr[index++],
381 GFP_KERNEL);
189 if (err) {382 if (err) {
190 dev_warn(dev->mt76.dev,383 dev_warn(dev->mt76.dev,
191 "failed setting NPU wlan tx buf addr\n");384 "failed setting NPU wlan tx buf addr\n");
192 return err;385 return err;
193 }386 }
194 387
195 if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024,388 err = mt76_npu_send_msg(npu, band + 10,
196 &dma_addr, GFP_KERNEL))
197 return -ENOMEM;
198
199 err = mt76_npu_send_msg(npu, i + 10,
200 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,389 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
201 dma_addr, GFP_KERNEL);390 dev->npu_txd_addr[index++],
391 GFP_KERNEL);
202 if (err) {392 if (err) {
203 dev_warn(dev->mt76.dev,393 dev_warn(dev->mt76.dev,
204 "failed setting NPU wlan tx buf base\n");394 "failed setting NPU wlan tx buf base\n");
@@ -212,8 +402,9 @@ static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu) · 7 unmodified lines
212static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,402static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,
213 struct airoha_npu *npu)403 struct airoha_npu *npu)
214{404{
215 struct mt76_queue *q = &dev->mt76.q_rx[MT_RXQ_MAIN_WA];405 int qid = is_mt7996(&dev->mt76) ? MT_RXQ_TXFREE_BAND0 : MT_RXQ_MAIN_WA;
216 phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;406 phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
407 struct mt76_queue *q = &dev->mt76.q_rx[qid];
217 int err;408 int err;
218 409
219 err = mt76_npu_send_msg(npu, 0,410 err = mt76_npu_send_msg(npu, 0,
@@ -233,7 +424,8 @@ static int mt7996_npu_rx_event_init(struct mt7996_dev *dev, · 13 unmodified lines
233 return err;424 return err;
234 }425 }
235 426
236 phy_addr += MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA) + 0x20;427 phy_addr += MT_RXQ_RING_BASE(qid);
428 phy_addr += is_mt7996(&dev->mt76) ? 0x90 : 0x20;
237 err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_PCIE_ADDR,429 err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
238 phy_addr, GFP_KERNEL);430 phy_addr, GFP_KERNEL);
239 if (err)431 if (err)
@@ -242,11 +434,54 @@ static int mt7996_npu_rx_event_init(struct mt7996_dev *dev, · 2 unmodified lines
242 return err;434 return err;
243}435}
244 436
437static int mt7996_npu_set_pcie_addr(struct mt7996_dev *dev,
438 struct airoha_npu *npu)
439{
440 u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
441 dma_addr_t dma_addr = dev->mt76.mmio.phy_addr;
442 int err;
443
444 dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0) + 0x80;
445 err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
446 dma_addr, GFP_KERNEL);
447 if (err) {
448 dev_warn(dev->mt76.dev,
449 "failed setting NPU wlan PCIe desc addr\n");
450 return err;
451 }
452
453 dma_addr = dev->mt76.mmio.phy_addr + hif1_ofs;
454 if (is_mt7996(&dev->mt76)) {
455 dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + 0x60;
456 err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
457 dma_addr, GFP_KERNEL);
458 } else {
459 dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + 0x90;
460 err = mt76_npu_send_msg(npu, 1, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
461 dma_addr, GFP_KERNEL);
462 }
463
464 if (err)
465 dev_warn(dev->mt76.dev,
466 "failed setting NPU wlan PCIe desc addr\n");
467
468 return err;
469}
470
245static int mt7996_npu_tx_done_init(struct mt7996_dev *dev,471static int mt7996_npu_tx_done_init(struct mt7996_dev *dev,
246 struct airoha_npu *npu)472 struct airoha_npu *npu)
247{473{
248 int err;474 int err;
249 475
476 /* rro ring cpu idx */
477 err = mt76_npu_send_msg(npu, 15, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
478 0, GFP_KERNEL);
479 if (err) {
480 dev_warn(dev->mt76.dev,
481 "failed setting NPU wlan PCIe desc addr\n");
482 return err;
483 }
484
250 err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,485 err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
251 0, GFP_KERNEL);486 0, GFP_KERNEL);
252 if (err) {487 if (err) {
@@ -278,40 +513,79 @@ int mt7996_npu_rx_queues_init(struct mt7996_dev *dev) · 25 unmodified lines
278 &dev->mt76.q_rx[MT_RXQ_NPU1]);513 &dev->mt76.q_rx[MT_RXQ_NPU1]);
279}514}
280 515
281int mt7996_npu_hw_init(struct mt7996_dev *dev)516int __mt7996_npu_hw_init(struct mt7996_dev *dev)
282{517{
283 struct airoha_npu *npu;518 struct airoha_npu *npu;
284 int i, err = 0;519 int i, err;
285
286 mutex_lock(&dev->mt76.mutex);
287 520
288 npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);521 npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
289 if (!npu)522 if (!npu)
290 goto unlock;523 return 0;
291 524
292 err = mt7996_npu_offload_init(dev, npu);525 err = mt7996_npu_offload_init(dev, npu);
293 if (err)526 if (err)
294 goto unlock;527 return err;
528
529 if (is_mt7996(&dev->mt76))
530 err = mt7996_npu_rxd_init(dev, npu);
531 else
532 err = mt7992_npu_rxd_init(dev, npu);
295 533
296 err = mt7996_npu_rxd_init(dev, npu);
297 if (err)534 if (err)
298 goto unlock;535 return err;
299 536
300 err = mt7996_npu_txd_init(dev, npu);537 err = mt7996_npu_txd_init(dev, npu);
301 if (err)538 if (err)
302 goto unlock;539 return err;
303 540
304 err = mt7996_npu_rx_event_init(dev, npu);541 err = mt7996_npu_rx_event_init(dev, npu);
305 if (err)542 if (err)
306 goto unlock;543 return err;
544
545 err = mt7996_npu_set_pcie_addr(dev, npu);
546 if (err)
547 return err;
307 548
308 err = mt7996_npu_tx_done_init(dev, npu);549 err = mt7996_npu_tx_done_init(dev, npu);
309 if (err)550 if (err)
310 goto unlock;551 return err;
311 552
312 for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++)553 for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++)
313 airoha_npu_wlan_enable_irq(npu, i - MT_RXQ_NPU0);554 airoha_npu_wlan_enable_irq(npu, i - MT_RXQ_NPU0);
314unlock:555
556 return 0;
557}
558
559int mt7996_npu_hw_init(struct mt7996_dev *dev)
560{
561 int i, err;
562
563 BUILD_BUG_ON(ARRAY_SIZE(dev->npu_txd_addr) % 3);
564
565 for (i = 0; i < ARRAY_SIZE(dev->npu_txd_addr); i += 3) {
566 int band = i && is_mt7996(&dev->mt76) ? MT_BAND2 : MT_BAND0;
567 u32 size = is_mt7996(&dev->mt76) ? band == MT_BAND2
568 ? MT7996_NPU_TX_RING_SIZE
569 : MT7996_NPU_RX_RING_SIZE / 2
570 : MT7996_TX_RING_SIZE;
571
572 if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * size,
573 &dev->npu_txd_addr[i], GFP_KERNEL))
574 return -ENOMEM;
575
576 if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * size,
577 &dev->npu_txd_addr[i + 1],
578 GFP_KERNEL))
579 return -ENOMEM;
580
581 if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024,
582 &dev->npu_txd_addr[i + 2],
583 GFP_KERNEL))
584 return -ENOMEM;
585 }
586
587 mutex_lock(&dev->mt76.mutex);
588 err = __mt7996_npu_hw_init(dev);
315 mutex_unlock(&dev->mt76.mutex);589 mutex_unlock(&dev->mt76.mutex);
316 590
317 return err;591 return err;
@@ -320,33 +594,38 @@ unlock: · 2 unmodified lines
320int mt7996_npu_hw_stop(struct mt7996_dev *dev)594int mt7996_npu_hw_stop(struct mt7996_dev *dev)
321{595{
322 struct airoha_npu *npu;596 struct airoha_npu *npu;
323 int i, err;597 int i, err = 0;
324 u32 info;598 u32 info;
325 599
600 mutex_lock(&dev->mt76.mutex);
601
326 npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);602 npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
327 if (!npu)603 if (!npu)
328 return 0;604 goto unlock;
329 605
330 err = mt76_npu_send_msg(npu, 4, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,606 err = mt76_npu_send_msg(npu, 4, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
331 0, GFP_KERNEL);607 0, GFP_KERNEL);
332 if (err)608 if (err)
333 return err;609 goto unlock;
334 610
335 for (i = 0; i < 10; i++) {611 for (i = 0; i < 10; i++) {
336 err = mt76_npu_get_msg(npu, 3, WLAN_FUNC_GET_WAIT_NPU_INFO,612 err = mt76_npu_get_msg(npu, 3, WLAN_FUNC_GET_WAIT_NPU_INFO,
337 &info, GFP_KERNEL);613 &info, GFP_KERNEL);
338 if (err)614 if (!err && !info)
339 continue;615 break;
340 616
341 if (info) {617 err = -ETIMEDOUT;
342 err = -ETIMEDOUT;618 usleep_range(10000, 15000);
343 continue;
344 }
345 }619 }
346 620
347 if (!err)621 if (!err)
348 err = mt76_npu_send_msg(npu, 6,622 err = mt76_npu_send_msg(npu, 6,
349 WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,623 WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
350 0, GFP_KERNEL);624 0, GFP_KERNEL);
625 else
626 dev_err(dev->mt76.dev, "npu stop failed\n");
627unlock:
628 mutex_unlock(&dev->mt76.mutex);
629
351 return err;630 return err;
352}631}
drivers/net/wireless/mediatek/mt76/mt7996/regs.h+11−0
@@ -159,6 +159,9 @@ enum offs_rev { · 158 unmodified lines
159#define MT_MDP_BASE 0x820cc000159#define MT_MDP_BASE 0x820cc000
160#define MT_MDP(ofs) (MT_MDP_BASE + (ofs))160#define MT_MDP(ofs) (MT_MDP_BASE + (ofs))
161 161
162#define MT_MDP_DCR0 MT_MDP(0x800)
163#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
164
162#define MT_MDP_DCR2 MT_MDP(0x8e8)165#define MT_MDP_DCR2 MT_MDP(0x8e8)
163#define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2)166#define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2)
164 167
@@ -733,7 +736,15 @@ enum offs_rev { · 568 unmodified lines
733#define MT_HW_REV 0x70010204736#define MT_HW_REV 0x70010204
734#define MT_HW_REV1 0x8a00737#define MT_HW_REV1 0x8a00
735 738
739#define MT_WF_L05_RST 0x70028550
740#define MT_WF_L05_RST_WF_RST_MASK GENMASK(4, 0)
741
736#define MT_WF_SUBSYS_RST 0x70028600742#define MT_WF_SUBSYS_RST 0x70028600
743#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST BIT(0)
744#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT BIT(5)
745#define MT_WF_SUBSYS_RST_BYPASS_WFDMA_SLP_PROT BIT(6)
746#define MT_WF_SUBSYS_RST_BYPASS_WFDMA2_SLP_PROT BIT(16)
747#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE GENMASK(15, 8)
737 748
738/* PCIE MAC */749/* PCIE MAC */
739#define MT_PCIE_MAC_BASE 0x74030000750#define MT_PCIE_MAC_BASE 0x74030000
drivers/net/wireless/mediatek/mt76/npu.c+32−5
@@ -390,6 +390,36 @@ int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 389 unmodified lines
390}390}
391EXPORT_SYMBOL_GPL(mt76_npu_net_setup_tc);391EXPORT_SYMBOL_GPL(mt76_npu_net_setup_tc);
392 392
393int mt76_npu_send_txrx_addr(struct mt76_dev *dev, int ifindex,
394 u32 direction, u32 i_count_addr,
395 u32 o_status_addr, u32 o_count_addr)
396{
397 struct {
398 __le32 dir;
399 __le32 in_count_addr;
400 __le32 out_status_addr;
401 __le32 out_count_addr;
402 } info = {
403 .dir = cpu_to_le32(direction),
404 .in_count_addr = cpu_to_le32(i_count_addr),
405 .out_status_addr = cpu_to_le32(o_status_addr),
406 .out_count_addr = cpu_to_le32(o_count_addr),
407 };
408 struct airoha_npu *npu;
409 int err = -ENODEV;
410
411 rcu_read_lock();
412 npu = rcu_dereference(dev->mmio.npu);
413 if (npu)
414 err = airoha_npu_wlan_send_msg(npu, ifindex,
415 WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
416 &info, sizeof(info), GFP_ATOMIC);
417 rcu_read_unlock();
418
419 return err;
420}
421EXPORT_SYMBOL_GPL(mt76_npu_send_txrx_addr);
422
393void mt76_npu_disable_irqs(struct mt76_dev *dev)423void mt76_npu_disable_irqs(struct mt76_dev *dev)
394{424{
395 struct airoha_npu *npu;425 struct airoha_npu *npu;
@@ -420,10 +450,6 @@ int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, int type) · 24 unmodified lines
420 struct airoha_npu *npu;450 struct airoha_npu *npu;
421 int err = 0;451 int err = 0;
422 452
423 /* NPU offloading is only supported by MT7992 */
424 if (!is_mt7992(dev))
425 return 0;
426
427 mutex_lock(&dev->mutex);453 mutex_lock(&dev->mutex);
428 454
429 npu = airoha_npu_get(dev->dev);455 npu = airoha_npu_get(dev->dev);
@@ -456,7 +482,8 @@ int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, int type) · 26 unmodified lines
456 dev->mmio.phy_addr = phy_addr;482 dev->mmio.phy_addr = phy_addr;
457 dev->mmio.npu_type = type;483 dev->mmio.npu_type = type;
458 /* NPU offloading requires HW-RRO for RX packet reordering. */484 /* NPU offloading requires HW-RRO for RX packet reordering. */
459 dev->hwrro_mode = MT76_HWRRO_V3_1;485 dev->hwrro_mode = is_mt7996(dev) ? MT76_HWRRO_V3 : MT76_HWRRO_V3_1;
486 dev->rx_token_size = 32768;
460 487
461 rcu_assign_pointer(dev->mmio.npu, npu);488 rcu_assign_pointer(dev->mmio.npu, npu);
462 rcu_assign_pointer(dev->mmio.ppe_dev, ppe_dev);489 rcu_assign_pointer(dev->mmio.ppe_dev, ppe_dev);
drivers/net/wireless/mediatek/mt76/scan.c+61−9
@@ -16,9 +16,11 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort) · 15 unmodified lines
16 16
17 clear_bit(MT76_SCANNING, &phy->state);17 clear_bit(MT76_SCANNING, &phy->state);
18 18
19 if (dev->scan.chan && phy->main_chandef.chan &&19 if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel &&
20 !test_bit(MT76_MCU_RESET, &dev->phy.state))20 !test_bit(MT76_MCU_RESET, &dev->phy.state)) {
21 mt76_set_channel(phy, &phy->main_chandef, false);21 mt76_set_channel(phy, &phy->main_chandef, false);
22 mt76_offchannel_notify(phy, false);
23 }
22 mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);24 mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);
23 memset(&dev->scan, 0, sizeof(dev->scan));25 memset(&dev->scan, 0, sizeof(dev->scan));
24 if (!test_bit(MT76_MCU_RESET, &dev->phy.state))26 if (!test_bit(MT76_MCU_RESET, &dev->phy.state))
@@ -27,6 +29,10 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort) · 2 unmodified lines
27 29
28void mt76_abort_scan(struct mt76_dev *dev)30void mt76_abort_scan(struct mt76_dev *dev)
29{31{
32 spin_lock_bh(&dev->scan_lock);
33 dev->scan.beacon_wait = false;
34 spin_unlock_bh(&dev->scan_lock);
35
30 cancel_delayed_work_sync(&dev->scan_work);36 cancel_delayed_work_sync(&dev->scan_work);
31 mt76_scan_complete(dev, true);37 mt76_scan_complete(dev, true);
32}38}
@@ -77,6 +83,27 @@ out: · 44 unmodified lines
77 rcu_read_unlock();83 rcu_read_unlock();
78}84}
79 85
86void mt76_scan_rx_beacon(struct mt76_dev *dev, struct ieee80211_channel *chan)
87{
88 struct mt76_phy *phy;
89
90 spin_lock(&dev->scan_lock);
91
92 if (!dev->scan.beacon_wait || dev->scan.beacon_received ||
93 dev->scan.chan != chan)
94 goto out;
95
96 phy = dev->scan.phy;
97 if (!phy)
98 goto out;
99
100 dev->scan.beacon_received = true;
101 ieee80211_queue_delayed_work(phy->hw, &dev->scan_work, 0);
102
103out:
104 spin_unlock(&dev->scan_lock);
105}
106
80void mt76_scan_work(struct work_struct *work)107void mt76_scan_work(struct work_struct *work)
81{108{
82 struct mt76_dev *dev = container_of(work, struct mt76_dev,109 struct mt76_dev *dev = container_of(work, struct mt76_dev,
@@ -85,35 +112,60 @@ void mt76_scan_work(struct work_struct *work) · 2 unmodified lines
85 struct cfg80211_chan_def chandef = {};112 struct cfg80211_chan_def chandef = {};
86 struct mt76_phy *phy = dev->scan.phy;113 struct mt76_phy *phy = dev->scan.phy;
87 int duration = HZ / 9; /* ~110 ms */114 int duration = HZ / 9; /* ~110 ms */
115 bool beacon_rx, offchannel = true;
88 int i;116 int i;
89 117
118 if (!phy || !req)
119 return;
120
121 spin_lock_bh(&dev->scan_lock);
122 beacon_rx = dev->scan.beacon_wait && dev->scan.beacon_received;
123 dev->scan.beacon_wait = false;
124 spin_unlock_bh(&dev->scan_lock);
125
126 if (beacon_rx)
127 goto probe;
128
90 if (dev->scan.chan_idx >= req->n_channels) {129 if (dev->scan.chan_idx >= req->n_channels) {
91 mt76_scan_complete(dev, false);130 mt76_scan_complete(dev, false);
92 return;131 return;
93 }132 }
94 133
95 if (dev->scan.chan && phy->num_sta) {134 if (dev->scan.chan && phy->num_sta && phy->offchannel) {
96 dev->scan.chan = NULL;135 dev->scan.chan = NULL;
97 mt76_set_channel(phy, &phy->main_chandef, false);136 mt76_set_channel(phy, &phy->main_chandef, false);
137 mt76_offchannel_notify(phy, false);
98 goto out;138 goto out;
99 }139 }
100 140
101 dev->scan.chan = req->channels[dev->scan.chan_idx++];141 dev->scan.chan = req->channels[dev->scan.chan_idx++];
102 cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20);142 offchannel = mt76_offchannel_chandef(phy, dev->scan.chan, &chandef);
103 mt76_set_channel(phy, &chandef, true);143
144 if (offchannel)
145 mt76_offchannel_notify(phy, true);
146 mt76_set_channel(phy, &chandef, offchannel);
104 147
105 if (!req->n_ssids ||148 if (!req->n_ssids)
106 chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
107 goto out;149 goto out;
108 150
109 duration = HZ / 16; /* ~60 ms */151 if (chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) {
152 spin_lock_bh(&dev->scan_lock);
153 dev->scan.beacon_received = false;
154 dev->scan.beacon_wait = true;
155 spin_unlock_bh(&dev->scan_lock);
156 goto out;
157 }
158
159probe:
160 if (phy->offchannel)
161 duration = HZ / 16; /* ~60 ms */
110 local_bh_disable();162 local_bh_disable();
111 for (i = 0; i < req->n_ssids; i++)163 for (i = 0; i < req->n_ssids; i++)
112 mt76_scan_send_probe(dev, &req->ssids[i]);164 mt76_scan_send_probe(dev, &req->ssids[i]);
113 local_bh_enable();165 local_bh_enable();
114 166
115out:167out:
116 if (dev->scan.chan)168 if (dev->scan.chan && phy->offchannel)
117 duration = max_t(int, duration,169 duration = max_t(int, duration,
118 msecs_to_jiffies(req->duration +170 msecs_to_jiffies(req->duration +
119 (req->duration >> 5)));171 (req->duration >> 5)));
drivers/net/wireless/mediatek/mt76/tx.c+31−3
@@ -227,7 +227,9 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid, · 226 unmodified lines
227 struct sk_buff *skb)227 struct sk_buff *skb)
228{228{
229 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);229 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
230 struct ieee80211_sta *sta;
230 int pending;231 int pending;
232 int i;
231 233
232 if (!wcid || info->tx_time_est)234 if (!wcid || info->tx_time_est)
233 return;235 return;
@@ -235,6 +237,17 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid, · 1 unmodified line
235 pending = atomic_dec_return(&wcid->non_aql_packets);237 pending = atomic_dec_return(&wcid->non_aql_packets);
236 if (pending < 0)238 if (pending < 0)
237 atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);239 atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
240
241 sta = wcid_to_sta(wcid);
242 if (!sta || pending != MT_MAX_NON_AQL_PKT - 1)
243 return;
244
245 for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
246 if (!sta->txq[i])
247 continue;
248
249 ieee80211_schedule_txq(dev->hw, sta->txq[i]);
250 }
238}251}
239 252
240void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb,253void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb,
@@ -542,6 +555,9 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) · 301 unmodified lines
542 if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))555 if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))
543 continue;556 continue;
544 557
558 if (atomic_read(&wcid->non_aql_packets) >= MT_MAX_NON_AQL_PKT)
559 continue;
560
545 phy = mt76_dev_phy(dev, wcid->phy_idx);561 phy = mt76_dev_phy(dev, wcid->phy_idx);
546 if (test_bit(MT76_RESET, &phy->state) || phy->offchannel)562 if (test_bit(MT76_RESET, &phy->state) || phy->offchannel)
547 continue;563 continue;
@@ -616,7 +632,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid, · 68 unmodified lines
616 632
617 if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&633 if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
618 !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&634 !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
619 !ieee80211_is_data(hdr->frame_control) &&635 !ieee80211_is_data_present(hdr->frame_control) &&
620 (!ieee80211_is_bufferable_mmpdu(skb) ||636 (!ieee80211_is_bufferable_mmpdu(skb) ||
621 ieee80211_is_deauth(hdr->frame_control) ||637 ieee80211_is_deauth(hdr->frame_control) ||
622 head == &wcid->tx_offchannel))638 head == &wcid->tx_offchannel))
@@ -644,7 +660,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid, · 21 unmodified lines
644 return ret;660 return ret;
645}661}
646 662
647static void mt76_txq_schedule_pending(struct mt76_phy *phy)663void mt76_txq_schedule_pending(struct mt76_phy *phy)
648{664{
649 LIST_HEAD(tx_list);665 LIST_HEAD(tx_list);
650 int ret = 0;666 int ret = 0;
@@ -850,9 +866,15 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi) · 199 unmodified lines
850 token = idr_alloc(&dev->token, *ptxwi, dev->token_start,866 token = idr_alloc(&dev->token, *ptxwi, dev->token_start,
851 dev->token_start + dev->token_size,867 dev->token_start + dev->token_size,
852 GFP_ATOMIC);868 GFP_ATOMIC);
853 if (token >= dev->token_start)869 if (token >= dev->token_start) {
854 dev->token_count++;870 dev->token_count++;
855 871
872 if ((*ptxwi)->qid == MT_TXQ_PSD) {
873 struct mt76_phy *mphy = mt76_dev_phy(dev, (*ptxwi)->phy_idx);
874 atomic_inc(&mphy->mgmt_tx_pending);
875 }
876 }
877
856#ifdef CONFIG_NET_MEDIATEK_SOC_WED878#ifdef CONFIG_NET_MEDIATEK_SOC_WED
857 if (mtk_wed_device_active(&dev->mmio.wed) &&879 if (mtk_wed_device_active(&dev->mmio.wed) &&
858 token >= dev->mmio.wed.wlan.token_start)880 token >= dev->mmio.wed.wlan.token_start)
@@ -897,6 +919,12 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake) · 38 unmodified lines
897 if (txwi) {919 if (txwi) {
898 dev->token_count--;920 dev->token_count--;
899 921
922 if (txwi->qid == MT_TXQ_PSD) {
923 struct mt76_phy *mphy = mt76_dev_phy(dev, txwi->phy_idx);
924 if (atomic_dec_and_test(&mphy->mgmt_tx_pending))
925 wake_up(&dev->tx_wait);
926 }
927
900#ifdef CONFIG_NET_MEDIATEK_SOC_WED928#ifdef CONFIG_NET_MEDIATEK_SOC_WED
901 if (mtk_wed_device_active(&dev->mmio.wed) &&929 if (mtk_wed_device_active(&dev->mmio.wed) &&
902 token >= dev->mmio.wed.wlan.token_start &&930 token >= dev->mmio.wed.wlan.token_start &&
drivers/net/wireless/mediatek/mt7601u/mcu.c+14−1
@@ -403,12 +403,18 @@ error: · 402 unmodified lines
403 return ret;403 return ret;
404}404}
405 405
406static const char * const mt7601u_fw_paths[] = {
407 "mediatek/" MT7601U_FIRMWARE,
408 MT7601U_FIRMWARE,
409};
410
406static int mt7601u_load_firmware(struct mt7601u_dev *dev)411static int mt7601u_load_firmware(struct mt7601u_dev *dev)
407{412{
408 const struct firmware *fw;413 const struct firmware *fw;
409 const struct mt76_fw_header *hdr;414 const struct mt76_fw_header *hdr;
410 int len, ret;415 int len, ret;
411 u32 val;416 u32 val;
417 int i;
412 418
413 mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |419 mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
414 MT_USB_DMA_CFG_TX_BULK_EN));420 MT_USB_DMA_CFG_TX_BULK_EN));
@@ -416,7 +422,14 @@ static int mt7601u_load_firmware(struct mt7601u_dev *dev) · 1 unmodified line
416 if (firmware_running(dev))422 if (firmware_running(dev))
417 return firmware_request_cache(dev->dev, MT7601U_FIRMWARE);423 return firmware_request_cache(dev->dev, MT7601U_FIRMWARE);
418 424
419 ret = request_firmware(&fw, MT7601U_FIRMWARE, dev->dev);425 /* Try loading firmware from multiple locations */
426 fw = NULL;
427 for (i = 0; i < MT7601U_FIRMWARE_PATHS; i++) {
428 ret = request_firmware(&fw, mt7601u_fw_paths[i], dev->dev);
429 if (ret == 0)
430 break;
431 }
432
420 if (ret)433 if (ret)
421 return ret;434 return ret;
422 435
drivers/net/wireless/mediatek/mt7601u/usb.h+1−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include "mt7601u.h"9#include "mt7601u.h"
10 10
11#define MT7601U_FIRMWARE "mt7601u.bin"11#define MT7601U_FIRMWARE "mt7601u.bin"
12#define MT7601U_FIRMWARE_PATHS ARRAY_SIZE(mt7601u_fw_paths)
12 13
13#define MT_VEND_REQ_MAX_RETRY 1014#define MT_VEND_REQ_MAX_RETRY 10
14#define MT_VEND_REQ_TOUT_MS 30015#define MT_VEND_REQ_TOUT_MS 300
drivers/net/wireless/virtual/mac80211_hwsim.c+35−0
@@ -4640,6 +4640,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = { · 4639 unmodified lines
4640 },4640 },
4641 /* PPE threshold information is not supported */4641 /* PPE threshold information is not supported */
4642 },4642 },
4643 .uhr_cap = {
4644 .has_uhr = true,
4645 .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
4646 IEEE80211_UHR_PHY_CAP_ELR_TX,
4647 },
4643 },4648 },
4644 {4649 {
4645 .types_mask = BIT(NL80211_IFTYPE_AP) |4650 .types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -4748,6 +4753,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = { · 102 unmodified lines
4748 },4753 },
4749 /* PPE threshold information is not supported */4754 /* PPE threshold information is not supported */
4750 },4755 },
4756 .uhr_cap = {
4757 .has_uhr = true,
4758 .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
4759 IEEE80211_UHR_PHY_CAP_ELR_TX,
4760 },
4751 },4761 },
4752#ifdef CONFIG_MAC80211_MESH4762#ifdef CONFIG_MAC80211_MESH
4753 {4763 {
@@ -4917,6 +4927,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = { · 163 unmodified lines
4917 },4927 },
4918 /* PPE threshold information is not supported */4928 /* PPE threshold information is not supported */
4919 },4929 },
4930 .uhr_cap = {
4931 .has_uhr = true,
4932 .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
4933 IEEE80211_UHR_PHY_CAP_ELR_TX,
4934 },
4920 },4935 },
4921 {4936 {
4922 .types_mask = BIT(NL80211_IFTYPE_AP) |4937 .types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -5042,6 +5057,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = { · 119 unmodified lines
5042 },5057 },
5043 /* PPE threshold information is not supported */5058 /* PPE threshold information is not supported */
5044 },5059 },
5060 .uhr_cap = {
5061 .has_uhr = true,
5062 .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
5063 IEEE80211_UHR_PHY_CAP_ELR_TX,
5064 },
5045 },5065 },
5046#ifdef CONFIG_MAC80211_MESH5066#ifdef CONFIG_MAC80211_MESH
5047 {5067 {
@@ -5235,6 +5255,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = { · 187 unmodified lines
5235 },5255 },
5236 /* PPE threshold information is not supported */5256 /* PPE threshold information is not supported */
5237 },5257 },
5258 .uhr_cap = {
5259 .has_uhr = true,
5260 .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
5261 IEEE80211_UHR_PHY_CAP_ELR_TX,
5262 },
5238 },5263 },
5239 {5264 {
5240 .types_mask = BIT(NL80211_IFTYPE_AP) |5265 .types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -5381,6 +5406,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = { · 140 unmodified lines
5381 },5406 },
5382 /* PPE threshold information is not supported */5407 /* PPE threshold information is not supported */
5383 },5408 },
5409 .uhr_cap = {
5410 .has_uhr = true,
5411 .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
5412 IEEE80211_UHR_PHY_CAP_ELR_TX,
5413 },
5384 },5414 },
5385#ifdef CONFIG_MAC80211_MESH5415#ifdef CONFIG_MAC80211_MESH
5386 {5416 {
@@ -5472,6 +5502,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = { · 85 unmodified lines
5472 },5502 },
5473 /* PPE threshold information is not supported */5503 /* PPE threshold information is not supported */
5474 },5504 },
5505 .uhr_cap = {
5506 .has_uhr = true,
5507 .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
5508 IEEE80211_UHR_PHY_CAP_ELR_TX,
5509 },
5475 },5510 },
5476#endif5511#endif
5477};5512};
include/linux/ieee80211-nan.h+6−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
9 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>9 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
10 * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH10 * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
11 * Copyright (c) 2016 - 2017 Intel Deutschland GmbH11 * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
12 * Copyright (c) 2018 - 2025 Intel Corporation12 * Copyright (c) 2018 - 2026 Intel Corporation
13 */13 */
14 14
15#ifndef LINUX_IEEE80211_NAN_H15#ifndef LINUX_IEEE80211_NAN_H
@@ -23,6 +23,11 @@ · 7 unmodified lines
23#define NAN_OP_MODE_160MHZ 0x0423#define NAN_OP_MODE_160MHZ 0x04
24#define NAN_OP_MODE_PNDL_SUPPRTED 0x0824#define NAN_OP_MODE_PNDL_SUPPRTED 0x08
25 25
26#define NAN_DEV_CAPA_NUM_TX_ANT_POS 0
27#define NAN_DEV_CAPA_NUM_TX_ANT_MASK 0x0f
28#define NAN_DEV_CAPA_NUM_RX_ANT_POS 4
29#define NAN_DEV_CAPA_NUM_RX_ANT_MASK 0xf0
30
26/* NAN Device capabilities, as defined in Wi-Fi Aware (TM) specification31/* NAN Device capabilities, as defined in Wi-Fi Aware (TM) specification
27 * Table 7932 * Table 79
28 */33 */
include/linux/ieee80211.h+7−0
@@ -1194,6 +1194,13 @@ struct ieee80211_mgmt { · 1193 unmodified lines
1194 1194
1195#define IEEE80211_MIN_ACTION_SIZE(type) offsetofend(struct ieee80211_mgmt, u.action.type)1195#define IEEE80211_MIN_ACTION_SIZE(type) offsetofend(struct ieee80211_mgmt, u.action.type)
1196 1196
1197/* Link Reconfiguration Status Duple field */
1198struct ieee80211_ml_reconf_status {
1199 u8 info;
1200 __le16 status;
1201} __packed;
1202
1203#define IEEE80211_ML_RECONF_LINK_ID_MASK 0xf
1197 1204
1198/* Management MIC information element (IEEE 802.11w) for CMAC */1205/* Management MIC information element (IEEE 802.11w) for CMAC */
1199struct ieee80211_mmie {1206struct ieee80211_mmie {
include/net/cfg80211.h+258−7
@@ -1831,6 +1831,7 @@ struct cfg80211_ttlm_params { · 1830 unmodified lines
1831 * @eml_cap: EML capabilities of this station1831 * @eml_cap: EML capabilities of this station
1832 * @link_sta_params: link related params.1832 * @link_sta_params: link related params.
1833 * @epp_peer: EPP peer indication1833 * @epp_peer: EPP peer indication
1834 * @nmi_mac: MAC address of the NMI station of the NAN peer
1834 */1835 */
1835struct station_parameters {1836struct station_parameters {
1836 struct net_device *vlan;1837 struct net_device *vlan;
@@ -1858,6 +1859,7 @@ struct station_parameters { · 21 unmodified lines
1858 u16 eml_cap;1859 u16 eml_cap;
1859 struct link_station_parameters link_sta_params;1860 struct link_station_parameters link_sta_params;
1860 bool epp_peer;1861 bool epp_peer;
1862 const u8 *nmi_mac;
1861};1863};
1862 1864
1863/**1865/**
@@ -1897,6 +1899,8 @@ struct station_del_parameters { · 33 unmodified lines
1897 * entry that is operating, has been marked authorized by userspace)1899 * entry that is operating, has been marked authorized by userspace)
1898 * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed)1900 * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed)
1899 * @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed)1901 * @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed)
1902 * @CFG80211_STA_NAN_MGMT: NAN management interface station
1903 * @CFG80211_STA_NAN_DATA: NAN data path station
1900 */1904 */
1901enum cfg80211_station_type {1905enum cfg80211_station_type {
1902 CFG80211_STA_AP_CLIENT,1906 CFG80211_STA_AP_CLIENT,
@@ -1908,6 +1912,8 @@ enum cfg80211_station_type { · 5 unmodified lines
1908 CFG80211_STA_TDLS_PEER_ACTIVE,1912 CFG80211_STA_TDLS_PEER_ACTIVE,
1909 CFG80211_STA_MESH_PEER_KERNEL,1913 CFG80211_STA_MESH_PEER_KERNEL,
1910 CFG80211_STA_MESH_PEER_USER,1914 CFG80211_STA_MESH_PEER_USER,
1915 CFG80211_STA_NAN_MGMT,
1916 CFG80211_STA_NAN_DATA,
1911};1917};
1912 1918
1913/**1919/**
@@ -3980,6 +3986,77 @@ struct cfg80211_qos_map { · 2066 unmodified lines
3980 struct cfg80211_dscp_range up[8];3986 struct cfg80211_dscp_range up[8];
3981};3987};
3982 3988
3989/**
3990 * DOC: Neighbor Awareness Networking (NAN)
3991 *
3992 * NAN uses two interface types:
3993 *
3994 * - %NL80211_IFTYPE_NAN: a non-netdev interface. This has two roles: (1) holds
3995 * the configuration of all NAN activities (DE parameters, synchronisation
3996 * parameters, local schedule, etc.), and (2) uses as the NAN Management
3997 * Interface (NMI), which is used for NAN management communication.
3998 *
3999 * - %NL80211_IFTYPE_NAN_DATA: The NAN Data Interface (NDI), used for data
4000 * communication with NAN peers.
4001 *
4002 * An NDI interface can only be started (IFF_UP) if the NMI one is running and
4003 * NAN is started. Before NAN is stopped, all associated NDI interfaces
4004 * must be stopped first.
4005 *
4006 * The local schedule specifies which channels the device is available on and
4007 * when. Must be cancelled before NAN is stopped.
4008 *
4009 * NAN Stations
4010 * ~~~~~~~~~~~~
4011 *
4012 * There are two types of stations corresponding to the two interface types:
4013 *
4014 * - NMI station: Represents the NAN peer. Peer-specific data such as the peer's
4015 * schedule and the HT, VHT and HE capabilities belongs to the NMI station.
4016 * Also used for Tx/Rx of NAN management frames to/from the peer.
4017 * Added on the %NL80211_IFTYPE_NAN interface.
4018 *
4019 * - NDI station: Used for Tx/Rx of data frames (and non-NAN management frames)
4020 * for a specific NDP established with the NAN peer. Added on the
4021 * %NL80211_IFTYPE_NAN_DATA interface.
4022 *
4023 * A peer may reuse its NMI address as the NDI address. In that case, two
4024 * separate stations should be added even though they share the same MAC
4025 * address.
4026 *
4027 * HT, VHT and HE capabilities should not changes after it was set. It is the
4028 * driver's responsibility to check that.
4029 *
4030 * An NDI station can only be added if the corresponding NMI station has already
4031 * been configured with HT (and possibly VHT and HE) capabilities. It is the
4032 * driver's responsibility to check that.
4033 *
4034 * All NDI stations must be removed before corresponding NMI station is removed.
4035 * Therefore, removing a NMI station implies that the associated NDI station(s)
4036 * (if any) will be removed first.
4037 *
4038 * NAN Dependencies
4039 * ~~~~~~~~~~~~~~~~
4040 *
4041 * The following diagram shows the dependencies between NAN components.
4042 * An arrow from A to B means A must be started/added before B, and B must be
4043 * stopped/removed before A:
4044 *
4045 * +-------------+
4046 * | NMI iface |---(local schedule)
4047 * +------+------+
4048 * / \
4049 * v v
4050 * +-----------+ +-------------+
4051 * | NDI iface | | NMI sta |---(peer schedule)
4052 * +-----+-----+ +------+------+
4053 * \ /
4054 * v v
4055 * +----------+
4056 * | NDI sta |
4057 * +----------+
4058 */
4059
3983/**4060/**
3984 * struct cfg80211_nan_band_config - NAN band specific configuration4061 * struct cfg80211_nan_band_config - NAN band specific configuration
3985 *4062 *
@@ -4050,6 +4127,102 @@ struct cfg80211_nan_conf { · 64 unmodified lines
4050 u16 vendor_elems_len;4127 u16 vendor_elems_len;
4051};4128};
4052 4129
4130#define CFG80211_NAN_SCHED_NUM_TIME_SLOTS 32
4131
4132/**
4133 * struct cfg80211_nan_channel - NAN channel configuration
4134 *
4135 * This struct defines a NAN channel configuration
4136 *
4137 * @chandef: the channel definition
4138 * @channel_entry: pointer to the Channel Entry blob as defined in Wi-Fi Aware
4139 * (TM) 4.0 specification Table 100 (Channel Entry format for the NAN
4140 * Availability attribute).
4141 * @rx_nss: number of spatial streams supported on this channel
4142 */
4143struct cfg80211_nan_channel {
4144 struct cfg80211_chan_def chandef;
4145 const u8 *channel_entry;
4146 u8 rx_nss;
4147};
4148
4149/**
4150 * struct cfg80211_nan_local_sched - NAN local schedule
4151 *
4152 * This struct defines NAN local schedule parameters
4153 *
4154 * @schedule: a mapping of time slots to chandef indexes in %nan_channels.
4155 * An unscheduled slot will be set to %NL80211_NAN_SCHED_NOT_AVAIL_SLOT.
4156 * @n_channels: number of channel definitions in %nan_channels.
4157 * @nan_avail_blob: pointer to NAN Availability attribute blob.
4158 * See %NL80211_ATTR_NAN_AVAIL_BLOB for more details.
4159 * @nan_avail_blob_len: length of the @nan_avail_blob in bytes.
4160 * @deferred: if true, the command containing this schedule configuration is a
4161 * request from the device to perform an announced schedule update. This
4162 * means that it needs to send the updated NAN availability to the peers,
4163 * and do the actual switch on the right time (i.e. at the end of the slot
4164 * after the slot in which the updated NAN Availability was sent).
4165 * See %NL80211_ATTR_NAN_SCHED_DEFERRED for more details.
4166 * If false, the schedule is applied immediately.
4167 * @nan_channels: array of NAN channel definitions that can be scheduled.
4168 */
4169struct cfg80211_nan_local_sched {
4170 u8 schedule[CFG80211_NAN_SCHED_NUM_TIME_SLOTS];
4171 u8 n_channels;
4172 const u8 *nan_avail_blob;
4173 u16 nan_avail_blob_len;
4174 bool deferred;
4175 struct cfg80211_nan_channel nan_channels[] __counted_by(n_channels);
4176};
4177
4178/**
4179 * struct cfg80211_nan_peer_map - NAN peer schedule map
4180 *
4181 * This struct defines a single NAN peer schedule map
4182 *
4183 * @map_id: map ID of this schedule map
4184 * @schedule: a mapping of time slots to chandef indexes in the schedule's
4185 * @nan_channels. Each slot lasts 16TUs. An unscheduled slot will be
4186 * set to %NL80211_NAN_SCHED_NOT_AVAIL_SLOT.
4187 */
4188struct cfg80211_nan_peer_map {
4189 u8 map_id;
4190 u8 schedule[CFG80211_NAN_SCHED_NUM_TIME_SLOTS];
4191};
4192
4193#define CFG80211_NAN_MAX_PEER_MAPS 2
4194#define CFG80211_NAN_INVALID_MAP_ID 0xff
4195
4196/**
4197 * struct cfg80211_nan_peer_sched - NAN peer schedule
4198 *
4199 * This struct defines NAN peer schedule parameters for a peer.
4200 *
4201 * @peer_addr: MAC address of the peer (NMI address)
4202 * @seq_id: sequence ID of the peer schedule.
4203 * @committed_dw: committed DW as published by the peer.
4204 * See %NL80211_ATTR_NAN_COMMITTED_DW
4205 * @max_chan_switch: maximum channel switch time in microseconds as published
4206 * by the peer. See %NL80211_ATTR_NAN_MAX_CHAN_SWITCH_TIME.
4207 * @init_ulw: initial ULWs as published by the peer.
4208 * @ulw_size: number of bytes in @init_ulw.
4209 * @n_channels: number of channel definitions in @nan_channels.
4210 * @nan_channels: array of NAN channel definitions for this schedule.
4211 * @maps: array of peer schedule maps. Unused entries have
4212 * map_id = %CFG80211_NAN_INVALID_MAP_ID.
4213 */
4214struct cfg80211_nan_peer_sched {
4215 const u8 *peer_addr;
4216 u8 seq_id;
4217 u16 committed_dw;
4218 u16 max_chan_switch;
4219 const u8 *init_ulw;
4220 u16 ulw_size;
4221 u8 n_channels;
4222 struct cfg80211_nan_channel *nan_channels;
4223 struct cfg80211_nan_peer_map maps[CFG80211_NAN_MAX_PEER_MAPS];
4224};
4225
4053/**4226/**
4054 * enum cfg80211_nan_conf_changes - indicates changed fields in NAN4227 * enum cfg80211_nan_conf_changes - indicates changed fields in NAN
4055 * configuration4228 * configuration
@@ -4830,6 +5003,19 @@ struct mgmt_frame_regs { · 774 unmodified lines
4830 * @nan_change_conf: changes NAN configuration. The changed parameters must5003 * @nan_change_conf: changes NAN configuration. The changed parameters must
4831 * be specified in @changes (using &enum cfg80211_nan_conf_changes);5004 * be specified in @changes (using &enum cfg80211_nan_conf_changes);
4832 * All other parameters must be ignored.5005 * All other parameters must be ignored.
5006 * @nan_set_local_sched: configure the local schedule for NAN. The schedule
5007 * consists of an array of %cfg80211_nan_channel and the schedule itself,
5008 * in which each entry maps each time slot to the channel on which the
5009 * radio should operate on. If the chandef of a NAN channel is not
5010 * changed, the channel entry must also remain unchanged. It is the
5011 * driver's responsibility to verify this.
5012 * @nan_set_peer_sched: configure the peer schedule for NAN. The schedule
5013 * consists of an array of %cfg80211_nan_channel and the schedule itself,
5014 * in which each entry maps each time slot to a channel on which the
5015 * radio should operate on. In addition, it contains more peer's schedule
5016 * information such as committed DW, etc. When updating an existing peer
5017 * schedule, the full new schedule is provided - partial updates are not
5018 * supported, and the new schedule completely replaces the previous one.
4833 *5019 *
4834 * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS5020 * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
4835 *5021 *
@@ -5207,7 +5393,12 @@ struct cfg80211_ops { · 371 unmodified lines
5207 struct wireless_dev *wdev,5393 struct wireless_dev *wdev,
5208 struct cfg80211_nan_conf *conf,5394 struct cfg80211_nan_conf *conf,
5209 u32 changes);5395 u32 changes);
5210 5396 int (*nan_set_local_sched)(struct wiphy *wiphy,
5397 struct wireless_dev *wdev,
5398 struct cfg80211_nan_local_sched *sched);
5399 int (*nan_set_peer_sched)(struct wiphy *wiphy,
5400 struct wireless_dev *wdev,
5401 struct cfg80211_nan_peer_sched *sched);
5211 int (*set_multicast_to_unicast)(struct wiphy *wiphy,5402 int (*set_multicast_to_unicast)(struct wiphy *wiphy,
5212 struct net_device *dev,5403 struct net_device *dev,
5213 const bool enabled);5404 const bool enabled);
@@ -5836,6 +6027,12 @@ enum wiphy_nan_flags { · 622 unmodified lines
5836 * @max_channel_switch_time: maximum channel switch time in milliseconds.6027 * @max_channel_switch_time: maximum channel switch time in milliseconds.
5837 * @dev_capabilities: NAN device capabilities as defined in Wi-Fi Aware (TM)6028 * @dev_capabilities: NAN device capabilities as defined in Wi-Fi Aware (TM)
5838 * specification Table 79 (Capabilities field).6029 * specification Table 79 (Capabilities field).
6030 * @phy: Band-agnostic capabilities for NAN data interfaces. Since NAN
6031 * operates on multiple channels simultaneously, these capabilities apply
6032 * across all bands. Valid only if NL80211_IFTYPE_NAN_DATA is supported.
6033 * @phy.ht: HT capabilities (mandatory for NAN data)
6034 * @phy.vht: VHT capabilities (optional)
6035 * @phy.he: HE capabilities (optional)
5839 */6036 */
5840struct wiphy_nan_capa {6037struct wiphy_nan_capa {
5841 u32 flags;6038 u32 flags;
@@ -5843,6 +6040,11 @@ struct wiphy_nan_capa { · 1 unmodified line
5843 u8 n_antennas;6040 u8 n_antennas;
5844 u16 max_channel_switch_time;6041 u16 max_channel_switch_time;
5845 u8 dev_capabilities;6042 u8 dev_capabilities;
6043 struct {
6044 struct ieee80211_sta_ht_cap ht;
6045 struct ieee80211_sta_vht_cap vht;
6046 struct ieee80211_sta_he_cap he;
6047 } phy;
5846};6048};
5847 6049
5848#define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff6050#define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff
@@ -6736,8 +6938,8 @@ enum ieee80211_ap_reg_power { · 887 unmodified lines
6736 * the P2P Device.6938 * the P2P Device.
6737 * @ps: powersave mode is enabled6939 * @ps: powersave mode is enabled
6738 * @ps_timeout: dynamic powersave timeout6940 * @ps_timeout: dynamic powersave timeout
6739 * @ap_unexpected_nlportid: (private) netlink port ID of application6941 * @unexpected_nlportid: (private) netlink port ID of application
6740 * registered for unexpected class 3 frames (AP mode)6942 * registered for unexpected frames (AP mode or NAN_DATA mode)
6741 * @conn: (private) cfg80211 software SME connection state machine data6943 * @conn: (private) cfg80211 software SME connection state machine data
6742 * @connect_keys: (private) keys to set after connection is established6944 * @connect_keys: (private) keys to set after connection is established
6743 * @conn_bss_type: connecting/connected BSS type6945 * @conn_bss_type: connecting/connected BSS type
@@ -6799,7 +7001,7 @@ struct wireless_dev { · 55 unmodified lines
6799 bool ps;7001 bool ps;
6800 int ps_timeout;7002 int ps_timeout;
6801 7003
6802 u32 ap_unexpected_nlportid;7004 u32 unexpected_nlportid;
6803 7005
6804 u32 owner_nlportid;7006 u32 owner_nlportid;
6805 bool nl_owner_dead;7007 bool nl_owner_dead;
@@ -6859,6 +7061,9 @@ struct wireless_dev { · 53 unmodified lines
6859 } ocb;7061 } ocb;
6860 struct {7062 struct {
6861 u8 cluster_id[ETH_ALEN] __aligned(2);7063 u8 cluster_id[ETH_ALEN] __aligned(2);
7064 u8 n_channels;
7065 struct cfg80211_chan_def *chandefs;
7066 bool sched_update_pending;
6862 } nan;7067 } nan;
6863 } u;7068 } u;
6864 7069
@@ -9367,9 +9572,10 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, · 2502 unmodified lines
9367 * @addr: the transmitter address9572 * @addr: the transmitter address
9368 * @gfp: context flags9573 * @gfp: context flags
9369 *9574 *
9370 * This function is used in AP mode (only!) to inform userspace that9575 * This function is used in AP mode to inform userspace that a spurious
9371 * a spurious class 3 frame was received, to be able to deauth the9576 * class 3 frame was received, to be able to deauth the sender.
9372 * sender.9577 * It is also used in NAN_DATA mode to report frames from unknown peers
9578 * (A2 not assigned to any active NDP), per Wi-Fi Aware (TM) 4.0 specification 6.2.5.
9373 * Return: %true if the frame was passed to userspace (or this failed9579 * Return: %true if the frame was passed to userspace (or this failed
9374 * for a reason other than not having a subscription.)9580 * for a reason other than not having a subscription.)
9375 */9581 */
@@ -10016,6 +10222,18 @@ void cfg80211_nan_func_terminated(struct wireless_dev *wdev, · 640 unmodified lines
10016 enum nl80211_nan_func_term_reason reason,10222 enum nl80211_nan_func_term_reason reason,
10017 u64 cookie, gfp_t gfp);10223 u64 cookie, gfp_t gfp);
10018 10224
10225/**
10226 * cfg80211_nan_sched_update_done - notify deferred schedule update completion
10227 * @wdev: the wireless device reporting the event
10228 * @success: whether or not the schedule update was successful
10229 * @gfp: allocation flags
10230 *
10231 * This function notifies user space that a deferred local NAN schedule update
10232 * (requested with %NL80211_ATTR_NAN_SCHED_DEFERRED) has been completed.
10233 */
10234void cfg80211_nan_sched_update_done(struct wireless_dev *wdev, bool success,
10235 gfp_t gfp);
10236
10019/* ethtool helper */10237/* ethtool helper */
10020void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);10238void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
10021 10239
@@ -10356,6 +10574,39 @@ void cfg80211_nan_cluster_joined(struct wireless_dev *wdev, · 334 unmodified lines
10356 const u8 *cluster_id, bool new_cluster,10574 const u8 *cluster_id, bool new_cluster,
10357 gfp_t gfp);10575 gfp_t gfp);
10358 10576
10577/**
10578 * cfg80211_nan_ulw_update - Notify user space about ULW update
10579 * @wdev: Pointer to the wireless device structure
10580 * @ulw: Pointer to the ULW blob data
10581 * @ulw_len: Length of the ULW blob in bytes
10582 * @gfp: Memory allocation flags
10583 *
10584 * This function is used by drivers to notify user space when the device's
10585 * ULW (Unaligned Schedule) blob has been updated. User space can use this
10586 * blob to attach to frames sent to peers.
10587 */
10588void cfg80211_nan_ulw_update(struct wireless_dev *wdev,
10589 const u8 *ulw, size_t ulw_len, gfp_t gfp);
10590
10591/**
10592 * cfg80211_nan_channel_evac - Notify user space about NAN channel evacuation
10593 * @wdev: Pointer to the wireless device structure
10594 * @chandef: Pointer to the channel definition of the NAN channel that was
10595 * evacuated
10596 * @gfp: Memory allocation flags
10597 *
10598 * This function is used by drivers to notify user space when a NAN
10599 * channel has been evacuated (i.e. ULWed) due to channel resource conflicts
10600 * with other interfaces.
10601 * This can happen when another interface sharing the channel resource with NAN
10602 * needs to move to a different channel (e.g. due to channel switch or link
10603 * switch). User space may reconfigure the local schedule to exclude the
10604 * evacuated channel.
10605 */
10606void cfg80211_nan_channel_evac(struct wireless_dev *wdev,
10607 const struct cfg80211_chan_def *chandef,
10608 gfp_t gfp);
10609
10359#ifdef CONFIG_CFG80211_DEBUGFS10610#ifdef CONFIG_CFG80211_DEBUGFS
10360/**10611/**
10361 * wiphy_locked_debugfs_read - do a locked read in debugfs10612 * wiphy_locked_debugfs_read - do a locked read in debugfs
include/uapi/linux/nl80211.h+229−3
@@ -906,8 +906,9 @@ · 905 unmodified lines
906 * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP906 * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
907 * (or GO) interface (i.e. hostapd) to ask for unexpected frames to907 * (or GO) interface (i.e. hostapd) to ask for unexpected frames to
908 * implement sending deauth to stations that send unexpected class 3908 * implement sending deauth to stations that send unexpected class 3
909 * frames. Also used as the event sent by the kernel when such a frame909 * frames. For NAN_DATA interfaces, this is used to report frames from
910 * is received.910 * unknown peers (A2 not assigned to any active NDP).
911 * Also used as the event sent by the kernel when such a frame is received.
911 * For the event, the %NL80211_ATTR_MAC attribute carries the TA and912 * For the event, the %NL80211_ATTR_MAC attribute carries the TA and
912 * other attributes like the interface index are present.913 * other attributes like the interface index are present.
913 * If used as the command it must have an interface index and you can914 * If used as the command it must have an interface index and you can
@@ -1367,6 +1368,53 @@ · 453 unmodified lines
1367 * %NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP. The current channel1368 * %NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP. The current channel
1368 * definition is also sent.1369 * definition is also sent.
1369 *1370 *
1371 * @NL80211_CMD_NAN_SET_LOCAL_SCHED: Set the local NAN schedule. NAN must be
1372 * operational (%NL80211_CMD_START_NAN was executed). Must contain
1373 * %NL80211_ATTR_NAN_TIME_SLOTS and %NL80211_ATTR_NAN_AVAIL_BLOB, but
1374 * %NL80211_ATTR_NAN_CHANNEL is optional (for example in case of a channel
1375 * removal, that channel won't be provided).
1376 * If %NL80211_ATTR_NAN_SCHED_DEFERRED is set, the command is a request
1377 * from the device to perform an announced schedule update. See
1378 * %NL80211_ATTR_NAN_SCHED_DEFERRED for more details.
1379 * If not set, the schedule should be applied immediately.
1380 * @NL80211_CMD_NAN_SCHED_UPDATE_DONE: Event sent to user space to notify that
1381 * a deferred local NAN schedule update (requested with
1382 * %NL80211_CMD_NAN_SET_LOCAL_SCHED and %NL80211_ATTR_NAN_SCHED_DEFERRED)
1383 * has been completed. The presence of %NL80211_ATTR_NAN_SCHED_UPDATE_SUCCESS
1384 * indicates that the update was successful.
1385 * @NL80211_CMD_NAN_SET_PEER_SCHED: Set the peer NAN schedule. NAN
1386 * must be operational (%NL80211_CMD_START_NAN was executed).
1387 * Required attributes: %NL80211_ATTR_MAC (peer NMI address) and
1388 * %NL80211_ATTR_NAN_COMMITTED_DW.
1389 * Optionally, the full schedule can be provided by including all of:
1390 * %NL80211_ATTR_NAN_SEQ_ID, %NL80211_ATTR_NAN_CHANNEL (one or more), and
1391 * %NL80211_ATTR_NAN_PEER_MAPS (see &enum nl80211_nan_peer_map_attrs).
1392 * If any of these three optional attributes is provided, all three must
1393 * be provided.
1394 * Each peer channel must be compatible with at least one local channel
1395 * set by %NL80211_CMD_SET_LOCAL_NAN_SCHED. Different maps must not
1396 * contain compatible channels.
1397 * For single-radio devices (n_radio <= 1), different maps must not
1398 * schedule the same time slot, as the device cannot operate on multiple
1399 * channels simultaneously.
1400 * When updating an existing peer schedule, the full new schedule must be
1401 * provided - partial updates are not supported. The new schedule will
1402 * completely replace the previous one.
1403 * The peer schedule is automatically removed when the NMI station is
1404 * removed.
1405 * @NL80211_CMD_NAN_ULW_UPDATE: Notification from the driver to user space
1406 * with the updated ULW blob of the device. User space can use this blob
1407 * to attach to frames sent to peers. This notification contains
1408 * %NL80211_ATTR_NAN_ULW with the ULW blob.
1409 * @NL80211_CMD_NAN_CHANNEL_EVAC: Notification to indicate that a NAN
1410 * channel has been evacuated due to resource conflicts with other
1411 * interfaces. This can happen when another interface sharing the channel
1412 * resource with NAN needs to move to a different channel (e.g., channel
1413 * switch or link switch on a BSS interface).
1414 * The notification contains %NL80211_ATTR_NAN_CHANNEL attribute
1415 * identifying the evacuated channel.
1416 * User space may reconfigure the local schedule in response to this
1417 * notification.
1370 * @NL80211_CMD_MAX: highest used command number1418 * @NL80211_CMD_MAX: highest used command number
1371 * @__NL80211_CMD_AFTER_LAST: internal use1419 * @__NL80211_CMD_AFTER_LAST: internal use
1372 */1420 */
@@ -1632,6 +1680,16 @@ enum nl80211_commands { · 259 unmodified lines
1632 1680
1633 NL80211_CMD_INCUMBENT_SIGNAL_DETECT,1681 NL80211_CMD_INCUMBENT_SIGNAL_DETECT,
1634 1682
1683 NL80211_CMD_NAN_SET_LOCAL_SCHED,
1684
1685 NL80211_CMD_NAN_SCHED_UPDATE_DONE,
1686
1687 NL80211_CMD_NAN_SET_PEER_SCHED,
1688
1689 NL80211_CMD_NAN_ULW_UPDATE,
1690
1691 NL80211_CMD_NAN_CHANNEL_EVAC,
1692
1635 /* add new commands above here */1693 /* add new commands above here */
1636 1694
1637 /* used to define NL80211_CMD_MAX below */1695 /* used to define NL80211_CMD_MAX below */
@@ -2659,7 +2717,8 @@ enum nl80211_commands { · 1021 unmodified lines
2659 * a flow is assigned on each round of the DRR scheduler.2717 * a flow is assigned on each round of the DRR scheduler.
2660 * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from2718 * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from
2661 * association request when used with NL80211_CMD_NEW_STATION). Can be set2719 * association request when used with NL80211_CMD_NEW_STATION). Can be set
2662 * only if %NL80211_STA_FLAG_WME is set.2720 * only if %NL80211_STA_FLAG_WME is set (except for NAN, which uses WME
2721 * anyway).
2663 *2722 *
2664 * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include2723 * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include
2665 * in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing2724 * in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing
@@ -2991,6 +3050,82 @@ enum nl80211_commands { · 325 unmodified lines
2991 * @NL80211_ATTR_DISABLE_UHR: Force UHR capable interfaces to disable3050 * @NL80211_ATTR_DISABLE_UHR: Force UHR capable interfaces to disable
2992 * this feature during association. This is a flag attribute.3051 * this feature during association. This is a flag attribute.
2993 * Currently only supported in mac80211 drivers.3052 * Currently only supported in mac80211 drivers.
3053 * @NL80211_ATTR_NAN_CHANNEL: This is a nested attribute. There can be multiple
3054 * attributes of this type, each one represents a channel definition and
3055 * consists of top-level attributes like %NL80211_ATTR_WIPHY_FREQ.
3056 * When used with %NL80211_CMD_NAN_SET_LOCAL_SCHED, it specifies
3057 * the channel definitions on which the radio needs to operate during
3058 * specific time slots. All of the channel definitions should be mutually
3059 * incompatible. With this command, %NL80211_ATTR_NAN_CHANNEL_ENTRY and
3060 * %NL80211_ATTR_NAN_RX_NSS are mandatory.
3061 * When used with %NL80211_CMD_NAN_SET_PEER_SCHED, it configures the
3062 * peer NAN channels. In that case, the channel definitions can be
3063 * compatible to each other, or even identical just with different RX NSS.
3064 * With this command, %NL80211_ATTR_NAN_CHANNEL_ENTRY and
3065 * %NL80211_ATTR_NAN_RX_NSS are mandatory.
3066 * The number of channels should fit the current configuration of channels
3067 * and the possible interface combinations.
3068 * If an existing NAN channel is changed but the chandef isn't, the
3069 * channel entry must also remain unchanged.
3070 * When used with %NL80211_CMD_NAN_CHANNEL_EVAC, this identifies the
3071 * channels that were evacuated.
3072 * @NL80211_ATTR_NAN_CHANNEL_ENTRY: a byte array of 6 bytes. contains the
3073 * Channel Entry as defined in Wi-Fi Aware (TM) 4.0 specification Table
3074 * 100 (Channel Entry format for the NAN Availability attribute).
3075 * @NL80211_ATTR_NAN_RX_NSS: (u8) RX NSS used for a NAN channel. This is
3076 * used with %NL80211_ATTR_NAN_CHANNEL when configuring NAN channels with
3077 * %NL80211_CMD_NAN_SET_LOCAL_SCHED or %NL80211_CMD_NAN_SET_PEER_SCHED.
3078 * @NL80211_ATTR_NAN_TIME_SLOTS: an array of u8 values and 32 cells. each value
3079 * maps a time slot to the chandef on which the radio should operate on in
3080 * that time. %NL80211_NAN_SCHED_NOT_AVAIL_SLOT indicates unscheduled.
3081 * The chandef is represented using its index, where the index is the
3082 * sequential number of the %NL80211_ATTR_NAN_CHANNEL attribute within all
3083 * the attributes of this type.
3084 * Each slots spans over 16TUs, hence the entire schedule spans over
3085 * 512TUs. Other slot durations and periods are currently not supported.
3086 * @NL80211_ATTR_NAN_AVAIL_BLOB: (Binary) The NAN Availability attribute blob,
3087 * including the attribute header, as defined in Wi-Fi Aware (TM) 4.0
3088 * specification Table 93 (NAN Availability attribute format). Required with
3089 * %NL80211_CMD_NAN_SET_LOCAL_SCHED to provide the raw NAN Availability
3090 * attribute. Used by the device to publish Schedule Update NAFs.
3091 * @NL80211_ATTR_NAN_SCHED_DEFERRED: Flag attribute used with
3092 * %NL80211_CMD_NAN_SET_LOCAL_SCHED. When present, the command is a
3093 * request from the device to perform an announced schedule update. This
3094 * means that it needs to send the updated NAN availability to the peers,
3095 * and do the actual switch on the right time (i.e. at the end of the slot
3096 * after the slot in which the updated NAN Availability was sent). Since
3097 * the slots management is done in the device, the update to the peers
3098 * needs to be sent by the device, so it knows the actual switch time.
3099 * If the flag is not set, the schedule should be applied immediately.
3100 * When this flag is set, the total number of NAN channels from both the
3101 * old and new schedules must not exceed the allowed number of local NAN
3102 * channels, because with deferred scheduling the old channels cannot be
3103 * removed before adding the new ones to free up space.
3104 * @NL80211_ATTR_NAN_SCHED_UPDATE_SUCCESS: flag attribute used with
3105 * %NL80211_CMD_NAN_SCHED_UPDATE_DONE to indicate that the deferred
3106 * schedule update completed successfully. If this flag is not present,
3107 * the update failed.
3108 * @NL80211_ATTR_NAN_NMI_MAC: The address of the NMI station to which this NDI
3109 * station belongs. Used with %NL80211_CMD_NEW_STATION when adding an NDI
3110 * station.
3111 * @NL80211_ATTR_NAN_ULW: (Binary) The initial ULW(s) as published by the
3112 * peer, as defined in the Wi-Fi Aware (TM) 4.0 specification Table 109
3113 * (Unaligned Schedule attribute format). Used to configure the device
3114 * with the initial ULW(s) of a peer, before the device starts tracking it.
3115 * @NL80211_ATTR_NAN_COMMITTED_DW: (u16) The committed DW as published by the
3116 * peer, as defined in the Wi-Fi Aware (TM) 4.0 specification Table 80
3117 * (Committed DW Information field format).
3118 * @NL80211_ATTR_NAN_SEQ_ID: (u8) The sequence ID of the peer schedule that
3119 * %NL80211_CMD_NAN_SET_PEER_SCHED defines. The device follows the
3120 * sequence ID in the frames to identify newer schedules. Once a schedule
3121 * with a higher sequence ID is received, the device may stop communicating
3122 * with that peer until a new peer schedule with a matching sequence ID is
3123 * received.
3124 * @NL80211_ATTR_NAN_MAX_CHAN_SWITCH_TIME: (u16) The maximum channel switch
3125 * time, in microseconds.
3126 * @NL80211_ATTR_NAN_PEER_MAPS: Nested array of peer schedule maps.
3127 * Used with %NL80211_CMD_NAN_SET_PEER_SCHED. Contains up to 2 entries,
3128 * each containing nested attributes from &enum nl80211_nan_peer_map_attrs.
2994 *3129 *
2995 * @NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP: u32 attribute specifying3130 * @NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP: u32 attribute specifying
2996 * the signal interference bitmap detected on the operating bandwidth for3131 * the signal interference bitmap detected on the operating bandwidth for
@@ -3582,6 +3717,22 @@ enum nl80211_attrs { · 585 unmodified lines
3582 3717
3583 NL80211_ATTR_UHR_OPERATION,3718 NL80211_ATTR_UHR_OPERATION,
3584 3719
3720 NL80211_ATTR_NAN_CHANNEL,
3721 NL80211_ATTR_NAN_CHANNEL_ENTRY,
3722 NL80211_ATTR_NAN_TIME_SLOTS,
3723 NL80211_ATTR_NAN_RX_NSS,
3724 NL80211_ATTR_NAN_AVAIL_BLOB,
3725 NL80211_ATTR_NAN_SCHED_DEFERRED,
3726 NL80211_ATTR_NAN_SCHED_UPDATE_SUCCESS,
3727
3728 NL80211_ATTR_NAN_NMI_MAC,
3729
3730 NL80211_ATTR_NAN_ULW,
3731 NL80211_ATTR_NAN_COMMITTED_DW,
3732 NL80211_ATTR_NAN_SEQ_ID,
3733 NL80211_ATTR_NAN_MAX_CHAN_SWITCH_TIME,
3734 NL80211_ATTR_NAN_PEER_MAPS,
3735
3585 /* add attributes here, update the policy in nl80211.c */3736 /* add attributes here, update the policy in nl80211.c */
3586 3737
3587 __NL80211_ATTR_AFTER_LAST,3738 __NL80211_ATTR_AFTER_LAST,
@@ -3675,6 +3826,9 @@ enum nl80211_attrs { · 87 unmodified lines
3675 * @NL80211_IFTYPE_OCB: Outside Context of a BSS3826 * @NL80211_IFTYPE_OCB: Outside Context of a BSS
3676 * This mode corresponds to the MIB variable dot11OCBActivated=true3827 * This mode corresponds to the MIB variable dot11OCBActivated=true
3677 * @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev)3828 * @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev)
3829 * @NL80211_IFTYPE_NAN_DATA: NAN data interface type (netdev); NAN data
3830 * interfaces can only be brought up (IFF_UP) when a NAN interface
3831 * already exists and NAN has been started (using %NL80211_CMD_START_NAN).
3678 * @NL80211_IFTYPE_MAX: highest interface type number currently defined3832 * @NL80211_IFTYPE_MAX: highest interface type number currently defined
3679 * @NUM_NL80211_IFTYPES: number of defined interface types3833 * @NUM_NL80211_IFTYPES: number of defined interface types
3680 *3834 *
@@ -3696,6 +3850,7 @@ enum nl80211_iftype { · 15 unmodified lines
3696 NL80211_IFTYPE_P2P_DEVICE,3850 NL80211_IFTYPE_P2P_DEVICE,
3697 NL80211_IFTYPE_OCB,3851 NL80211_IFTYPE_OCB,
3698 NL80211_IFTYPE_NAN,3852 NL80211_IFTYPE_NAN,
3853 NL80211_IFTYPE_NAN_DATA,
3699 3854
3700 /* keep last */3855 /* keep last */
3701 NUM_NL80211_IFTYPES,3856 NUM_NL80211_IFTYPES,
@@ -4384,6 +4539,46 @@ enum nl80211_band_attr { · 682 unmodified lines
4384 4539
4385#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA4540#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
4386 4541
4542/**
4543 * enum nl80211_nan_phy_cap_attr - NAN PHY capabilities attributes
4544 * @__NL80211_NAN_PHY_CAP_ATTR_INVALID: attribute number 0 is reserved
4545 * @NL80211_NAN_PHY_CAP_ATTR_HT_MCS_SET: 16-byte attribute containing HT MCS set
4546 * @NL80211_NAN_PHY_CAP_ATTR_HT_CAPA: HT capabilities (u16)
4547 * @NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_FACTOR: HT A-MPDU factor (u8)
4548 * @NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_DENSITY: HT A-MPDU density (u8)
4549 * @NL80211_NAN_PHY_CAP_ATTR_VHT_MCS_SET: 8-byte attribute containing VHT MCS set
4550 * @NL80211_NAN_PHY_CAP_ATTR_VHT_CAPA: VHT capabilities (u32)
4551 * @NL80211_NAN_PHY_CAP_ATTR_HE_MAC: HE MAC capabilities
4552 * @NL80211_NAN_PHY_CAP_ATTR_HE_PHY: HE PHY capabilities
4553 * @NL80211_NAN_PHY_CAP_ATTR_HE_MCS_SET: HE supported NSS/MCS combinations
4554 * @NL80211_NAN_PHY_CAP_ATTR_HE_PPE: HE PPE thresholds
4555 * @NL80211_NAN_PHY_CAP_ATTR_MAX: highest NAN PHY cap attribute number
4556 * @__NL80211_NAN_PHY_CAP_ATTR_AFTER_LAST: internal use
4557 */
4558enum nl80211_nan_phy_cap_attr {
4559 __NL80211_NAN_PHY_CAP_ATTR_INVALID,
4560
4561 /* HT capabilities */
4562 NL80211_NAN_PHY_CAP_ATTR_HT_MCS_SET,
4563 NL80211_NAN_PHY_CAP_ATTR_HT_CAPA,
4564 NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_FACTOR,
4565 NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_DENSITY,
4566
4567 /* VHT capabilities */
4568 NL80211_NAN_PHY_CAP_ATTR_VHT_MCS_SET,
4569 NL80211_NAN_PHY_CAP_ATTR_VHT_CAPA,
4570
4571 /* HE capabilities */
4572 NL80211_NAN_PHY_CAP_ATTR_HE_MAC,
4573 NL80211_NAN_PHY_CAP_ATTR_HE_PHY,
4574 NL80211_NAN_PHY_CAP_ATTR_HE_MCS_SET,
4575 NL80211_NAN_PHY_CAP_ATTR_HE_PPE,
4576
4577 /* keep last */
4578 __NL80211_NAN_PHY_CAP_ATTR_AFTER_LAST,
4579 NL80211_NAN_PHY_CAP_ATTR_MAX = __NL80211_NAN_PHY_CAP_ATTR_AFTER_LAST - 1
4580};
4581
4387/**4582/**
4388 * enum nl80211_wmm_rule - regulatory wmm rule4583 * enum nl80211_wmm_rule - regulatory wmm rule
4389 *4584 *
@@ -8557,6 +8752,8 @@ enum nl80211_s1g_short_beacon_attrs { · 4167 unmodified lines
8557 * @NL80211_NAN_CAPA_CAPABILITIES: u8 attribute containing the8752 * @NL80211_NAN_CAPA_CAPABILITIES: u8 attribute containing the
8558 * capabilities of the device as defined in Wi-Fi Aware (TM)8753 * capabilities of the device as defined in Wi-Fi Aware (TM)
8559 * specification Table 79 (Capabilities field).8754 * specification Table 79 (Capabilities field).
8755 * @NL80211_NAN_CAPA_PHY: nested attribute containing band-agnostic
8756 * capabilities for NAN data path. See &enum nl80211_nan_phy_cap_attr.
8560 * @__NL80211_NAN_CAPABILITIES_LAST: Internal8757 * @__NL80211_NAN_CAPABILITIES_LAST: Internal
8561 * @NL80211_NAN_CAPABILITIES_MAX: Highest NAN capability attribute.8758 * @NL80211_NAN_CAPABILITIES_MAX: Highest NAN capability attribute.
8562 */8759 */
@@ -8569,9 +8766,38 @@ enum nl80211_nan_capabilities { · 6 unmodified lines
8569 NL80211_NAN_CAPA_NUM_ANTENNAS,8766 NL80211_NAN_CAPA_NUM_ANTENNAS,
8570 NL80211_NAN_CAPA_MAX_CHANNEL_SWITCH_TIME,8767 NL80211_NAN_CAPA_MAX_CHANNEL_SWITCH_TIME,
8571 NL80211_NAN_CAPA_CAPABILITIES,8768 NL80211_NAN_CAPA_CAPABILITIES,
8769 NL80211_NAN_CAPA_PHY,
8572 /* keep last */8770 /* keep last */
8573 __NL80211_NAN_CAPABILITIES_LAST,8771 __NL80211_NAN_CAPABILITIES_LAST,
8574 NL80211_NAN_CAPABILITIES_MAX = __NL80211_NAN_CAPABILITIES_LAST - 1,8772 NL80211_NAN_CAPABILITIES_MAX = __NL80211_NAN_CAPABILITIES_LAST - 1,
8575};8773};
8576 8774
8775/**
8776 * enum nl80211_nan_peer_map_attrs - NAN peer schedule map attributes
8777 *
8778 * Nested attributes used within %NL80211_ATTR_NAN_PEER_MAPS to define
8779 * individual peer schedule maps.
8780 *
8781 * @__NL80211_NAN_PEER_MAP_ATTR_INVALID: Invalid
8782 * @NL80211_NAN_PEER_MAP_ATTR_MAP_ID: (u8) The map ID for this schedule map.
8783 * @NL80211_NAN_PEER_MAP_ATTR_TIME_SLOTS: An array of u8 values with 32 cells.
8784 * Each value maps a time slot to a channel index within the schedule's
8785 * channel list (%NL80211_ATTR_NAN_CHANNEL attributes).
8786 * %NL80211_NAN_SCHED_NOT_AVAIL_SLOT indicates unscheduled.
8787 * @__NL80211_NAN_PEER_MAP_ATTR_LAST: Internal
8788 * @NL80211_NAN_PEER_MAP_ATTR_MAX: Highest peer map attribute
8789 */
8790enum nl80211_nan_peer_map_attrs {
8791 __NL80211_NAN_PEER_MAP_ATTR_INVALID,
8792
8793 NL80211_NAN_PEER_MAP_ATTR_MAP_ID,
8794 NL80211_NAN_PEER_MAP_ATTR_TIME_SLOTS,
8795
8796 /* keep last */
8797 __NL80211_NAN_PEER_MAP_ATTR_LAST,
8798 NL80211_NAN_PEER_MAP_ATTR_MAX = __NL80211_NAN_PEER_MAP_ATTR_LAST - 1,
8799};
8800
8801#define NL80211_NAN_SCHED_NOT_AVAIL_SLOT 0xff
8802
8577#endif /* __LINUX_NL80211_H */8803#endif /* __LINUX_NL80211_H */
net/mac80211/cfg.c+3−1
@@ -718,6 +718,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev, · 717 unmodified lines
718 case NL80211_IFTYPE_P2P_CLIENT:718 case NL80211_IFTYPE_P2P_CLIENT:
719 case NL80211_IFTYPE_P2P_GO:719 case NL80211_IFTYPE_P2P_GO:
720 case NL80211_IFTYPE_OCB:720 case NL80211_IFTYPE_OCB:
721 case NL80211_IFTYPE_NAN_DATA:
721 /* shouldn't happen */722 /* shouldn't happen */
722 WARN_ON_ONCE(1);723 WARN_ON_ONCE(1);
723 break;724 break;
@@ -2140,12 +2141,13 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, · 1416 unmodified lines
2140 return -EINVAL;2141 return -EINVAL;
2141 2142
2142 if (params->ht_capa)2143 if (params->ht_capa)
2143 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,2144 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, &sband->ht_cap,
2144 params->ht_capa, link_sta);2145 params->ht_capa, link_sta);
2145 2146
2146 /* VHT can override some HT caps such as the A-MSDU max length */2147 /* VHT can override some HT caps such as the A-MSDU max length */
2147 if (params->vht_capa)2148 if (params->vht_capa)
2148 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,2149 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
2150 &sband->vht_cap,
2149 params->vht_capa, NULL,2151 params->vht_capa, NULL,
2150 link_sta);2152 link_sta);
2151 2153
net/mac80211/chan.c+123−76
@@ -166,6 +166,13 @@ int ieee80211_chanctx_refcount(struct ieee80211_local *local, · 165 unmodified lines
166 for_each_chanctx_user_all(local, ctx, &iter)166 for_each_chanctx_user_all(local, ctx, &iter)
167 num++;167 num++;
168 168
169 /*
170 * This ctx is in the process of getting used,
171 * take it into consideration
172 */
173 if (ctx->will_be_used)
174 num++;
175
169 return num;176 return num;
170}177}
171 178
@@ -447,74 +454,94 @@ ieee80211_get_max_required_bw(struct ieee80211_link_data *link) · 275 unmodified lines
447 return max_bw;454 return max_bw;
448}455}
449 456
457static enum nl80211_chan_width
458ieee80211_get_width_of_link(struct ieee80211_link_data *link)
459{
460 struct ieee80211_local *local = link->sdata->local;
461
462 switch (link->sdata->vif.type) {
463 case NL80211_IFTYPE_STATION:
464 if (!link->sdata->vif.cfg.assoc) {
465 /*
466 * The AP's sta->bandwidth may not yet be set
467 * at this point (pre-association), so simply
468 * take the width from the chandef. We cannot
469 * have TDLS peers yet (only after association).
470 */
471 return link->conf->chanreq.oper.width;
472 }
473 /*
474 * otherwise just use min_def like in AP, depending on what
475 * we currently think the AP STA (and possibly TDLS peers)
476 * require(s)
477 */
478 fallthrough;
479 case NL80211_IFTYPE_AP:
480 case NL80211_IFTYPE_AP_VLAN:
481 return ieee80211_get_max_required_bw(link);
482 case NL80211_IFTYPE_P2P_DEVICE:
483 case NL80211_IFTYPE_NAN:
484 break;
485 case NL80211_IFTYPE_MONITOR:
486 WARN_ON_ONCE(!ieee80211_hw_check(&local->hw,
487 NO_VIRTUAL_MONITOR));
488 fallthrough;
489 case NL80211_IFTYPE_ADHOC:
490 case NL80211_IFTYPE_MESH_POINT:
491 case NL80211_IFTYPE_OCB:
492 return link->conf->chanreq.oper.width;
493 case NL80211_IFTYPE_WDS:
494 case NL80211_IFTYPE_UNSPECIFIED:
495 case NUM_NL80211_IFTYPES:
496 case NL80211_IFTYPE_P2P_CLIENT:
497 case NL80211_IFTYPE_P2P_GO:
498 case NL80211_IFTYPE_NAN_DATA:
499 WARN_ON_ONCE(1);
500 break;
501 }
502
503 /* Take the lowest possible, so it won't change the max width */
504 return NL80211_CHAN_WIDTH_20_NOHT;
505}
506
450static enum nl80211_chan_width507static enum nl80211_chan_width
451ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,508ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
452 struct ieee80211_chanctx *ctx,509 struct ieee80211_chanctx *ctx,
453 struct ieee80211_link_data *rsvd_for,510 struct ieee80211_link_data *rsvd_for,
454 bool check_reserved)511 bool check_reserved)
455{512{
456 struct ieee80211_sub_if_data *sdata;
457 struct ieee80211_link_data *link;
458 enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;513 enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
514 struct ieee80211_chanctx_user_iter iter;
515 struct ieee80211_sub_if_data *sdata;
516 enum nl80211_chan_width width;
459 517
460 if (WARN_ON(check_reserved && rsvd_for))518 if (WARN_ON(check_reserved && rsvd_for))
461 return ctx->conf.def.width;519 return ctx->conf.def.width;
462 520
463 for_each_sdata_link(local, link) {521 /* When this is true we only care about the reserving links */
464 enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;522 if (check_reserved) {
465 523 for_each_chanctx_user_reserved(local, ctx, &iter) {
466 if (check_reserved) {524 width = ieee80211_get_width_of_link(iter.link);
467 if (link->reserved_chanctx != ctx)525 max_bw = max(max_bw, width);
468 continue;
469 } else if (link != rsvd_for &&
470 rcu_access_pointer(link->conf->chanctx_conf) != &ctx->conf)
471 continue;
472
473 switch (link->sdata->vif.type) {
474 case NL80211_IFTYPE_STATION:
475 if (!link->sdata->vif.cfg.assoc) {
476 /*
477 * The AP's sta->bandwidth may not yet be set
478 * at this point (pre-association), so simply
479 * take the width from the chandef. We cannot
480 * have TDLS peers yet (only after association).
481 */
482 width = link->conf->chanreq.oper.width;
483 break;
484 }
485 /*
486 * otherwise just use min_def like in AP, depending on what
487 * we currently think the AP STA (and possibly TDLS peers)
488 * require(s)
489 */
490 fallthrough;
491 case NL80211_IFTYPE_AP:
492 case NL80211_IFTYPE_AP_VLAN:
493 width = ieee80211_get_max_required_bw(link);
494 break;
495 case NL80211_IFTYPE_P2P_DEVICE:
496 case NL80211_IFTYPE_NAN:
497 continue;
498 case NL80211_IFTYPE_MONITOR:
499 WARN_ON_ONCE(!ieee80211_hw_check(&local->hw,
500 NO_VIRTUAL_MONITOR));
501 fallthrough;
502 case NL80211_IFTYPE_ADHOC:
503 case NL80211_IFTYPE_MESH_POINT:
504 case NL80211_IFTYPE_OCB:
505 width = link->conf->chanreq.oper.width;
506 break;
507 case NL80211_IFTYPE_WDS:
508 case NL80211_IFTYPE_UNSPECIFIED:
509 case NUM_NL80211_IFTYPES:
510 case NL80211_IFTYPE_P2P_CLIENT:
511 case NL80211_IFTYPE_P2P_GO:
512 WARN_ON_ONCE(1);
513 }526 }
527 goto check_monitor;
528 }
514 529
530 /* Consider all assigned links */
531 for_each_chanctx_user_assigned(local, ctx, &iter) {
532 width = ieee80211_get_width_of_link(iter.link);
515 max_bw = max(max_bw, width);533 max_bw = max(max_bw, width);
516 }534 }
517 535
536 if (!rsvd_for ||
537 rsvd_for->sdata == rcu_access_pointer(local->monitor_sdata))
538 goto check_monitor;
539
540 /* Consider the link for which this chanctx is reserved/going to be assigned */
541 width = ieee80211_get_width_of_link(rsvd_for);
542 max_bw = max(max_bw, width);
543
544check_monitor:
518 /* use the configured bandwidth in case of monitor interface */545 /* use the configured bandwidth in case of monitor interface */
519 sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);546 sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
520 if (sdata &&547 if (sdata &&
@@ -752,10 +779,9 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local, · 231 unmodified lines
752 _ieee80211_change_chanctx(local, ctx, old_ctx, chanreq, NULL);779 _ieee80211_change_chanctx(local, ctx, old_ctx, chanreq, NULL);
753}780}
754 781
755/* Note: if successful, the returned chanctx is reserved for the link */782/* Note: if successful, the returned chanctx will_be_used flag is set */
756static struct ieee80211_chanctx *783static struct ieee80211_chanctx *
757ieee80211_find_chanctx(struct ieee80211_local *local,784ieee80211_find_chanctx(struct ieee80211_local *local,
758 struct ieee80211_link_data *link,
759 const struct ieee80211_chan_req *chanreq,785 const struct ieee80211_chan_req *chanreq,
760 enum ieee80211_chanctx_mode mode)786 enum ieee80211_chanctx_mode mode)
761{787{
@@ -767,9 +793,6 @@ ieee80211_find_chanctx(struct ieee80211_local *local, · 5 unmodified lines
767 if (mode == IEEE80211_CHANCTX_EXCLUSIVE)793 if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
768 return NULL;794 return NULL;
769 795
770 if (WARN_ON(link->reserved_chanctx))
771 return NULL;
772
773 list_for_each_entry(ctx, &local->chanctx_list, list) {796 list_for_each_entry(ctx, &local->chanctx_list, list) {
774 const struct ieee80211_chan_req *compat;797 const struct ieee80211_chan_req *compat;
775 798
@@ -790,12 +813,12 @@ ieee80211_find_chanctx(struct ieee80211_local *local, · 14 unmodified lines
790 continue;813 continue;
791 814
792 /*815 /*
793 * Reserve the chanctx temporarily, as the driver might change816 * Mark the chanctx as will be used, as the driver might change
794 * active links during callbacks we make into it below and/or817 * active links during callbacks we make into it below and/or
795 * later during assignment, which could (otherwise) cause the818 * later during assignment, which could (otherwise) cause the
796 * context to actually be removed.819 * context to actually be removed.
797 */820 */
798 link->reserved_chanctx = ctx;821 ctx->will_be_used = true;
799 822
800 ieee80211_change_chanctx(local, ctx, ctx, compat);823 ieee80211_change_chanctx(local, ctx, ctx, compat);
801 824
@@ -1438,6 +1461,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link) · 636 unmodified lines
1438 case NL80211_IFTYPE_P2P_GO:1461 case NL80211_IFTYPE_P2P_GO:
1439 case NL80211_IFTYPE_P2P_DEVICE:1462 case NL80211_IFTYPE_P2P_DEVICE:
1440 case NL80211_IFTYPE_NAN:1463 case NL80211_IFTYPE_NAN:
1464 case NL80211_IFTYPE_NAN_DATA:
1441 case NUM_NL80211_IFTYPES:1465 case NUM_NL80211_IFTYPES:
1442 WARN_ON(1);1466 WARN_ON(1);
1443 break;1467 break;
@@ -2011,6 +2035,36 @@ void __ieee80211_link_release_channel(struct ieee80211_link_data *link, · 567 unmodified lines
2011 ieee80211_vif_use_reserved_switch(local);2035 ieee80211_vif_use_reserved_switch(local);
2012}2036}
2013 2037
2038static struct ieee80211_chanctx *
2039ieee80211_find_or_create_chanctx(struct ieee80211_sub_if_data *sdata,
2040 const struct ieee80211_chan_req *chanreq,
2041 enum ieee80211_chanctx_mode mode,
2042 bool assign_on_failure,
2043 bool *reused_ctx)
2044{
2045 struct ieee80211_local *local = sdata->local;
2046 struct ieee80211_chanctx *ctx;
2047 int radio_idx;
2048
2049 lockdep_assert_wiphy(local->hw.wiphy);
2050
2051 ctx = ieee80211_find_chanctx(local, chanreq, mode);
2052 if (ctx) {
2053 *reused_ctx = true;
2054 return ctx;
2055 }
2056
2057 *reused_ctx = false;
2058
2059 if (!ieee80211_find_available_radio(local, chanreq,
2060 sdata->wdev.radio_mask,
2061 &radio_idx))
2062 return ERR_PTR(-EBUSY);
2063
2064 return ieee80211_new_chanctx(local, chanreq, mode,
2065 assign_on_failure, radio_idx);
2066}
2067
2014int _ieee80211_link_use_channel(struct ieee80211_link_data *link,2068int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
2015 const struct ieee80211_chan_req *chanreq,2069 const struct ieee80211_chan_req *chanreq,
2016 enum ieee80211_chanctx_mode mode,2070 enum ieee80211_chanctx_mode mode,
@@ -2020,8 +2074,7 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, · 3 unmodified lines
2020 struct ieee80211_local *local = sdata->local;2074 struct ieee80211_local *local = sdata->local;
2021 struct ieee80211_chanctx *ctx;2075 struct ieee80211_chanctx *ctx;
2022 u8 radar_detect_width = 0;2076 u8 radar_detect_width = 0;
2023 bool reserved = false;2077 bool reused_ctx = false;
2024 int radio_idx;
2025 int ret;2078 int ret;
2026 2079
2027 lockdep_assert_wiphy(local->hw.wiphy);2080 lockdep_assert_wiphy(local->hw.wiphy);
@@ -2049,17 +2102,8 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, · 21 unmodified lines
2049 if (!local->in_reconfig)2102 if (!local->in_reconfig)
2050 __ieee80211_link_release_channel(link, false);2103 __ieee80211_link_release_channel(link, false);
2051 2104
2052 ctx = ieee80211_find_chanctx(local, link, chanreq, mode);2105 ctx = ieee80211_find_or_create_chanctx(sdata, chanreq, mode,
2053 /* Note: context is now reserved */2106 assign_on_failure, &reused_ctx);
2054 if (ctx)
2055 reserved = true;
2056 else if (!ieee80211_find_available_radio(local, chanreq,
2057 sdata->wdev.radio_mask,
2058 &radio_idx))
2059 ctx = ERR_PTR(-EBUSY);
2060 else
2061 ctx = ieee80211_new_chanctx(local, chanreq, mode,
2062 assign_on_failure, radio_idx);
2063 if (IS_ERR(ctx)) {2107 if (IS_ERR(ctx)) {
2064 ret = PTR_ERR(ctx);2108 ret = PTR_ERR(ctx);
2065 goto out;2109 goto out;
@@ -2069,10 +2113,13 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, · 3 unmodified lines
2069 2113
2070 ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);2114 ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);
2071 2115
2072 if (reserved) {2116 /*
2073 /* remove reservation */2117 * In case an existing channel context is being used, we marked it as
2074 WARN_ON(link->reserved_chanctx != ctx);2118 * will_be_used, now that it is assigned - clear this indication
2075 link->reserved_chanctx = NULL;2119 */
2120 if (reused_ctx) {
2121 WARN_ON(!ctx->will_be_used);
2122 ctx->will_be_used = false;
2076 }2123 }
2077 2124
2078 if (ret) {2125 if (ret) {
net/mac80211/he.c+24−13
@@ -108,14 +108,13 @@ static void ieee80211_he_mcs_intersection(__le16 *he_own_rx, __le16 *he_peer_rx, · 107 unmodified lines
108}108}
109 109
110void110void
111ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,111_ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
112 struct ieee80211_supported_band *sband,112 const struct ieee80211_sta_he_cap *own_he_cap_ptr,
113 const u8 *he_cap_ie, u8 he_cap_len,113 const u8 *he_cap_ie, u8 he_cap_len,
114 const struct ieee80211_he_6ghz_capa *he_6ghz_capa,114 const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
115 struct link_sta_info *link_sta)115 struct link_sta_info *link_sta)
116{116{
117 struct ieee80211_sta_he_cap *he_cap = &link_sta->pub->he_cap;117 struct ieee80211_sta_he_cap *he_cap = &link_sta->pub->he_cap;
118 const struct ieee80211_sta_he_cap *own_he_cap_ptr;
119 struct ieee80211_sta_he_cap own_he_cap;118 struct ieee80211_sta_he_cap own_he_cap;
120 struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie;119 struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie;
121 u8 he_ppe_size;120 u8 he_ppe_size;
@@ -125,12 +124,7 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, · 3 unmodified lines
125 124
126 memset(he_cap, 0, sizeof(*he_cap));125 memset(he_cap, 0, sizeof(*he_cap));
127 126
128 if (!he_cap_ie)127 if (!he_cap_ie || !own_he_cap_ptr || !own_he_cap_ptr->has_he)
129 return;
130
131 own_he_cap_ptr =
132 ieee80211_get_he_iftype_cap_vif(sband, &sdata->vif);
133 if (!own_he_cap_ptr)
134 return;128 return;
135 129
136 own_he_cap = *own_he_cap_ptr;130 own_he_cap = *own_he_cap_ptr;
@@ -164,7 +158,7 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, · 27 unmodified lines
164 link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta);158 link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta);
165 link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);159 link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
166 160
167 if (sband->band == NL80211_BAND_6GHZ && he_6ghz_capa)161 if (he_6ghz_capa)
168 ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, link_sta);162 ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, link_sta);
169 163
170 ieee80211_he_mcs_intersection(&own_he_cap.he_mcs_nss_supp.rx_mcs_80,164 ieee80211_he_mcs_intersection(&own_he_cap.he_mcs_nss_supp.rx_mcs_80,
@@ -207,6 +201,23 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, · 36 unmodified lines
207 }201 }
208}202}
209 203
204void
205ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
206 struct ieee80211_supported_band *sband,
207 const u8 *he_cap_ie, u8 he_cap_len,
208 const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
209 struct link_sta_info *link_sta)
210{
211 const struct ieee80211_sta_he_cap *own_he_cap =
212 ieee80211_get_he_iftype_cap_vif(sband, &sdata->vif);
213
214 _ieee80211_he_cap_ie_to_sta_he_cap(sdata, own_he_cap, he_cap_ie,
215 he_cap_len,
216 (sband->band == NL80211_BAND_6GHZ) ?
217 he_6ghz_capa : NULL,
218 link_sta);
219}
220
210void221void
211ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,222ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,
212 const struct ieee80211_he_operation *he_op_ie)223 const struct ieee80211_he_operation *he_op_ie)
net/mac80211/ht.c+3−3
@@ -136,7 +136,7 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, · 135 unmodified lines
136 136
137 137
138bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,138bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
139 struct ieee80211_supported_band *sband,139 const struct ieee80211_sta_ht_cap *own_cap_ptr,
140 const struct ieee80211_ht_cap *ht_cap_ie,140 const struct ieee80211_ht_cap *ht_cap_ie,
141 struct link_sta_info *link_sta)141 struct link_sta_info *link_sta)
142{142{
@@ -151,12 +151,12 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, · 8 unmodified lines
151 151
152 memset(&ht_cap, 0, sizeof(ht_cap));152 memset(&ht_cap, 0, sizeof(ht_cap));
153 153
154 if (!ht_cap_ie || !sband->ht_cap.ht_supported)154 if (!ht_cap_ie || !own_cap_ptr->ht_supported)
155 goto apply;155 goto apply;
156 156
157 ht_cap.ht_supported = true;157 ht_cap.ht_supported = true;
158 158
159 own_cap = sband->ht_cap;159 own_cap = *own_cap_ptr;
160 160
161 /*161 /*
162 * If user has specified capability over-rides, take care162 * If user has specified capability over-rides, take care
net/mac80211/ibss.c+3−1
@@ -1014,7 +1014,8 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, · 1013 unmodified lines
1014 ieee80211_chandef_ht_oper(elems->ht_operation, &chandef);1014 ieee80211_chandef_ht_oper(elems->ht_operation, &chandef);
1015 1015
1016 memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));1016 memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
1017 rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,1017 rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata,
1018 &sband->ht_cap,
1018 &htcap_ie,1019 &htcap_ie,
1019 &sta->deflink);1020 &sta->deflink);
1020 1021
@@ -1033,6 +1034,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, · 12 unmodified lines
1033 &chandef);1034 &chandef);
1034 memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));1035 memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
1035 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,1036 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
1037 &sband->vht_cap,
1036 &cap_ie, NULL,1038 &cap_ie, NULL,
1037 &sta->deflink);1039 &sta->deflink);
1038 if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap)))1040 if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap)))
net/mac80211/ieee80211_i.h+11−1
@@ -928,6 +928,9 @@ struct ieee80211_chanctx { · 927 unmodified lines
928 928
929 bool radar_detected;929 bool radar_detected;
930 930
931 /* This chanctx is in process of getting used */
932 bool will_be_used;
933
931 /* MUST be last - ends in a flexible-array member. */934 /* MUST be last - ends in a flexible-array member. */
932 struct ieee80211_chanctx_conf conf;935 struct ieee80211_chanctx_conf conf;
933};936};
@@ -2185,7 +2188,7 @@ void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, · 1251 unmodified lines
2185void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,2188void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
2186 struct ieee80211_sta_ht_cap *ht_cap);2189 struct ieee80211_sta_ht_cap *ht_cap);
2187bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,2190bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
2188 struct ieee80211_supported_band *sband,2191 const struct ieee80211_sta_ht_cap *own_cap,
2189 const struct ieee80211_ht_cap *ht_cap_ie,2192 const struct ieee80211_ht_cap *ht_cap_ie,
2190 struct link_sta_info *link_sta);2193 struct link_sta_info *link_sta);
2191void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,2194void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
@@ -2270,6 +2273,7 @@ void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local, · 78 unmodified lines
2270void2273void
2271ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,2274ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
2272 struct ieee80211_supported_band *sband,2275 struct ieee80211_supported_band *sband,
2276 const struct ieee80211_sta_vht_cap *own_vht_cap,
2273 const struct ieee80211_vht_cap *vht_cap_ie,2277 const struct ieee80211_vht_cap *vht_cap_ie,
2274 const struct ieee80211_vht_cap *vht_cap_ie2,2278 const struct ieee80211_vht_cap *vht_cap_ie2,
2275 struct link_sta_info *link_sta);2279 struct link_sta_info *link_sta);
@@ -2310,6 +2314,12 @@ ieee80211_sta_rx_bw_to_chan_width(struct link_sta_info *sta); · 34 unmodified lines
2310 2314
2311/* HE */2315/* HE */
2312void2316void
2317_ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
2318 const struct ieee80211_sta_he_cap *own_he_cap,
2319 const u8 *he_cap_ie, u8 he_cap_len,
2320 const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
2321 struct link_sta_info *link_sta);
2322void
2313ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,2323ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
2314 struct ieee80211_supported_band *sband,2324 struct ieee80211_supported_band *sband,
2315 const u8 *he_cap_ie, u8 he_cap_len,2325 const u8 *he_cap_ie, u8 he_cap_len,
net/mac80211/iface.c+18−10
@@ -1222,14 +1222,14 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local, · 1221 unmodified lines
1222 }1222 }
1223 }1223 }
1224 1224
1225 set_bit(SDATA_STATE_RUNNING, &sdata->state);
1226
1227 ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR);1225 ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR);
1228 if (ret) {1226 if (ret) {
1229 kfree(sdata);1227 kfree(sdata);
1230 return ret;1228 return ret;
1231 }1229 }
1232 1230
1231 set_bit(SDATA_STATE_RUNNING, &sdata->state);
1232
1233 mutex_lock(&local->iflist_mtx);1233 mutex_lock(&local->iflist_mtx);
1234 rcu_assign_pointer(local->monitor_sdata, sdata);1234 rcu_assign_pointer(local->monitor_sdata, sdata);
1235 mutex_unlock(&local->iflist_mtx);1235 mutex_unlock(&local->iflist_mtx);
@@ -1242,6 +1242,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local, · 6 unmodified lines
1242 mutex_unlock(&local->iflist_mtx);1242 mutex_unlock(&local->iflist_mtx);
1243 synchronize_net();1243 synchronize_net();
1244 drv_remove_interface(local, sdata);1244 drv_remove_interface(local, sdata);
1245 clear_bit(SDATA_STATE_RUNNING, &sdata->state);
1245 kfree(sdata);1246 kfree(sdata);
1246 return ret;1247 return ret;
1247 }1248 }
@@ -1360,8 +1361,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 112 unmodified lines
1360 break;1361 break;
1361 }1362 }
1362 case NL80211_IFTYPE_AP:1363 case NL80211_IFTYPE_AP:
1363 sdata->bss = &sdata->u.ap;
1364 break;
1365 case NL80211_IFTYPE_MESH_POINT:1364 case NL80211_IFTYPE_MESH_POINT:
1366 case NL80211_IFTYPE_STATION:1365 case NL80211_IFTYPE_STATION:
1367 case NL80211_IFTYPE_MONITOR:1366 case NL80211_IFTYPE_MONITOR:
@@ -1369,6 +1368,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 1 unmodified line
1369 case NL80211_IFTYPE_P2P_DEVICE:1368 case NL80211_IFTYPE_P2P_DEVICE:
1370 case NL80211_IFTYPE_OCB:1369 case NL80211_IFTYPE_OCB:
1371 case NL80211_IFTYPE_NAN:1370 case NL80211_IFTYPE_NAN:
1371 case NL80211_IFTYPE_NAN_DATA:
1372 /* no special treatment */1372 /* no special treatment */
1373 break;1373 break;
1374 case NL80211_IFTYPE_UNSPECIFIED:1374 case NL80211_IFTYPE_UNSPECIFIED:
@@ -1386,8 +1386,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 11 unmodified lines
1386 local->reconfig_failure = false;1386 local->reconfig_failure = false;
1387 1387
1388 res = drv_start(local);1388 res = drv_start(local);
1389 if (res)1389 if (res) {
1390 goto err_del_bss;1390 /*
1391 * no need to worry about AP_VLAN cleanup since in that
1392 * case we can't have open_count == 0
1393 */
1394 return res;
1395 }
1391 ieee80211_led_radio(local, true);1396 ieee80211_led_radio(local, true);
1392 ieee80211_mod_tpt_led_trig(local,1397 ieee80211_mod_tpt_led_trig(local,
1393 IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);1398 IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
@@ -1458,6 +1463,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 64 unmodified lines
1458 netif_carrier_on(dev);1463 netif_carrier_on(dev);
1459 list_add_tail_rcu(&sdata->u.mntr.list, &local->mon_list);1464 list_add_tail_rcu(&sdata->u.mntr.list, &local->mon_list);
1460 break;1465 break;
1466 case NL80211_IFTYPE_AP:
1467 sdata->bss = &sdata->u.ap;
1468 fallthrough;
1461 default:1469 default:
1462 if (coming_up) {1470 if (coming_up) {
1463 ieee80211_del_virtual_monitor(local);1471 ieee80211_del_virtual_monitor(local);
@@ -1546,12 +1554,10 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 82 unmodified lines
1546 err_stop:1554 err_stop:
1547 if (!local->open_count)1555 if (!local->open_count)
1548 drv_stop(local, false);1556 drv_stop(local, false);
1549 err_del_bss:
1550 sdata->bss = NULL;
1551 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)1557 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1552 list_del(&sdata->u.vlan.list);1558 list_del(&sdata->u.vlan.list);
1553 /* might already be clear but that doesn't matter */1559 /* Might not be initialized yet, but it is harmless */
1554 clear_bit(SDATA_STATE_RUNNING, &sdata->state);1560 sdata->bss = NULL;
1555 return res;1561 return res;
1556}1562}
1557 1563
@@ -1940,6 +1946,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, · 382 unmodified lines
1940 case NL80211_IFTYPE_P2P_DEVICE:1946 case NL80211_IFTYPE_P2P_DEVICE:
1941 sdata->vif.bss_conf.bssid = sdata->vif.addr;1947 sdata->vif.bss_conf.bssid = sdata->vif.addr;
1942 break;1948 break;
1949 case NL80211_IFTYPE_NAN_DATA:
1950 break;
1943 case NL80211_IFTYPE_UNSPECIFIED:1951 case NL80211_IFTYPE_UNSPECIFIED:
1944 case NL80211_IFTYPE_WDS:1952 case NL80211_IFTYPE_WDS:
1945 case NUM_NL80211_IFTYPES:1953 case NUM_NL80211_IFTYPES:
net/mac80211/mesh_plink.c+2−1
@@ -450,12 +450,13 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, · 449 unmodified lines
450 changed |= IEEE80211_RC_SUPP_RATES_CHANGED;450 changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
451 sta->sta.deflink.supp_rates[sband->band] = rates;451 sta->sta.deflink.supp_rates[sband->band] = rates;
452 452
453 if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,453 if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, &sband->ht_cap,
454 elems->ht_cap_elem,454 elems->ht_cap_elem,
455 &sta->deflink))455 &sta->deflink))
456 changed |= IEEE80211_RC_BW_CHANGED;456 changed |= IEEE80211_RC_BW_CHANGED;
457 457
458 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,458 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
459 &sband->vht_cap,
459 elems->vht_cap_elem, NULL,460 elems->vht_cap_elem, NULL,
460 &sta->deflink);461 &sta->deflink);
461 462
net/mac80211/mlme.c+10−7
@@ -5586,7 +5586,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, · 5585 unmodified lines
5586 5586
5587 /* Set up internal HT/VHT capabilities */5587 /* Set up internal HT/VHT capabilities */
5588 if (elems->ht_cap_elem && link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HT)5588 if (elems->ht_cap_elem && link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HT)
5589 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,5589 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, &sband->ht_cap,
5590 elems->ht_cap_elem,5590 elems->ht_cap_elem,
5591 link_sta);5591 link_sta);
5592 5592
@@ -5622,6 +5622,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, · 29 unmodified lines
5622 }5622 }
5623 5623
5624 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,5624 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
5625 &sband->vht_cap,
5625 elems->vht_cap_elem,5626 elems->vht_cap_elem,
5626 bss_vht_cap, link_sta);5627 bss_vht_cap, link_sta);
5627 rcu_read_unlock();5628 rcu_read_unlock();
@@ -10458,8 +10459,8 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata, · 4830 unmodified lines
10458 pos = mgmt->u.action.ml_reconf_resp.variable;10459 pos = mgmt->u.action.ml_reconf_resp.variable;
10459 len -= offsetofend(typeof(*mgmt), u.action.ml_reconf_resp);10460 len -= offsetofend(typeof(*mgmt), u.action.ml_reconf_resp);
10460 10461
10461 /* each status duple is 3 octets */10462 if (len < mgmt->u.action.ml_reconf_resp.count *
10462 if (len < mgmt->u.action.ml_reconf_resp.count * 3) {10463 sizeof(struct ieee80211_ml_reconf_status)) {
10463 sdata_info(sdata,10464 sdata_info(sdata,
10464 "mlo: reconf: unexpected len=%zu, count=%u\n",10465 "mlo: reconf: unexpected len=%zu, count=%u\n",
10465 len, mgmt->u.action.ml_reconf_resp.count);10466 len, mgmt->u.action.ml_reconf_resp.count);
@@ -10468,9 +10469,11 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata, · 2 unmodified lines
10468 10469
10469 link_mask = sta_changed_links;10470 link_mask = sta_changed_links;
10470 for (i = 0; i < mgmt->u.action.ml_reconf_resp.count; i++) {10471 for (i = 0; i < mgmt->u.action.ml_reconf_resp.count; i++) {
10471 u16 status = get_unaligned_le16(pos + 1);10472 struct ieee80211_ml_reconf_status *reconf_status = (void *)pos;
10473 u16 status = le16_to_cpu(reconf_status->status);
10472 10474
10473 link_id = *pos;10475 link_id = u8_get_bits(reconf_status->info,
10476 IEEE80211_ML_RECONF_LINK_ID_MASK);
10474 10477
10475 if (!(link_mask & BIT(link_id))) {10478 if (!(link_mask & BIT(link_id))) {
10476 sdata_info(sdata,10479 sdata_info(sdata,
@@ -10505,8 +10508,8 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata, · 28 unmodified lines
10505 sdata->u.mgd.reconf.added_links &= ~BIT(link_id);10508 sdata->u.mgd.reconf.added_links &= ~BIT(link_id);
10506 }10509 }
10507 10510
10508 pos += 3;10511 pos += sizeof(*reconf_status);
10509 len -= 3;10512 len -= sizeof(*reconf_status);
10510 }10513 }
10511 10514
10512 if (link_mask) {10515 if (link_mask) {
net/mac80211/rx.c+2−0
@@ -4607,6 +4607,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) · 4606 unmodified lines
4607 (ieee80211_is_public_action(hdr, skb->len) ||4607 (ieee80211_is_public_action(hdr, skb->len) ||
4608 (ieee80211_is_auth(hdr->frame_control) &&4608 (ieee80211_is_auth(hdr->frame_control) &&
4609 ether_addr_equal(sdata->vif.addr, hdr->addr1)));4609 ether_addr_equal(sdata->vif.addr, hdr->addr1)));
4610 case NL80211_IFTYPE_NAN_DATA:
4611 return false;
4610 default:4612 default:
4611 break;4613 break;
4612 }4614 }
net/mac80211/trace.h+2−3
@@ -1778,9 +1778,8 @@ TRACE_EVENT(drv_switch_vif_chanctx, · 1777 unmodified lines
1778 SWITCH_ENTRY_ASSIGN(vif.vif_type, vif->type);1778 SWITCH_ENTRY_ASSIGN(vif.vif_type, vif->type);
1779 SWITCH_ENTRY_ASSIGN(vif.p2p, vif->p2p);1779 SWITCH_ENTRY_ASSIGN(vif.p2p, vif->p2p);
1780 SWITCH_ENTRY_ASSIGN(link_id, link_conf->link_id);1780 SWITCH_ENTRY_ASSIGN(link_id, link_conf->link_id);
1781 strncpy(local_vifs[i].vif.vif_name,1781 strscpy_pad(local_vifs[i].vif.vif_name,
1782 sdata->name,1782 sdata->name);
1783 sizeof(local_vifs[i].vif.vif_name));
1784 SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,1783 SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,
1785 old_ctx->def.chan->center_freq);1784 old_ctx->def.chan->center_freq);
1786 SWITCH_ENTRY_ASSIGN(old_chandef.freq_offset,1785 SWITCH_ENTRY_ASSIGN(old_chandef.freq_offset,
net/mac80211/util.c+1−0
@@ -2118,6 +2118,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) · 2117 unmodified lines
2118 return res;2118 return res;
2119 }2119 }
2120 break;2120 break;
2121 case NL80211_IFTYPE_NAN_DATA:
2121 case NL80211_IFTYPE_AP_VLAN:2122 case NL80211_IFTYPE_AP_VLAN:
2122 case NL80211_IFTYPE_MONITOR:2123 case NL80211_IFTYPE_MONITOR:
2123 case NL80211_IFTYPE_P2P_DEVICE:2124 case NL80211_IFTYPE_P2P_DEVICE:
net/mac80211/vht.c+18−15
@@ -4,7 +4,7 @@ · 3 unmodified lines
4 *4 *
5 * Portions of this file5 * Portions of this file
6 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH6 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
7 * Copyright (C) 2018-2026 Intel Corporation7 * Copyright (C) 2018 - 2026 Intel Corporation
8 */8 */
9 9
10#include <linux/ieee80211.h>10#include <linux/ieee80211.h>
@@ -115,6 +115,7 @@ void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, · 104 unmodified lines
115void115void
116ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,116ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
117 struct ieee80211_supported_band *sband,117 struct ieee80211_supported_band *sband,
118 const struct ieee80211_sta_vht_cap *own_vht_cap,
118 const struct ieee80211_vht_cap *vht_cap_ie,119 const struct ieee80211_vht_cap *vht_cap_ie,
119 const struct ieee80211_vht_cap *vht_cap_ie2,120 const struct ieee80211_vht_cap *vht_cap_ie2,
120 struct link_sta_info *link_sta)121 struct link_sta_info *link_sta)
@@ -122,7 +123,6 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, · 1 unmodified line
122 struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;123 struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;
123 struct ieee80211_sta_vht_cap own_cap;124 struct ieee80211_sta_vht_cap own_cap;
124 u32 cap_info, i;125 u32 cap_info, i;
125 bool have_80mhz;
126 u32 mpdu_len;126 u32 mpdu_len;
127 127
128 memset(vht_cap, 0, sizeof(*vht_cap));128 memset(vht_cap, 0, sizeof(*vht_cap));
@@ -130,22 +130,25 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, · 1 unmodified line
130 if (!link_sta->pub->ht_cap.ht_supported)130 if (!link_sta->pub->ht_cap.ht_supported)
131 return;131 return;
132 132
133 if (!vht_cap_ie || !sband->vht_cap.vht_supported)133 if (!vht_cap_ie || !own_vht_cap->vht_supported)
134 return;134 return;
135 135
136 /* Allow VHT if at least one channel on the sband supports 80 MHz */136 if (sband) {
137 have_80mhz = false;137 /* Allow VHT if at least one channel on the sband supports 80 MHz */
138 for (i = 0; i < sband->n_channels; i++) {138 bool have_80mhz = false;
139 if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
140 IEEE80211_CHAN_NO_80MHZ))
141 continue;
142 139
143 have_80mhz = true;140 for (i = 0; i < sband->n_channels; i++) {
144 break;141 if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
145 }142 IEEE80211_CHAN_NO_80MHZ))
143 continue;
146 144
147 if (!have_80mhz)145 have_80mhz = true;
148 return;146 break;
147 }
148
149 if (!have_80mhz)
150 return;
151 }
149 152
150 /*153 /*
151 * A VHT STA must support 40 MHz, but if we verify that here154 * A VHT STA must support 40 MHz, but if we verify that here
@@ -156,7 +159,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, · 4 unmodified lines
156 159
157 vht_cap->vht_supported = true;160 vht_cap->vht_supported = true;
158 161
159 own_cap = sband->vht_cap;162 own_cap = *own_vht_cap;
160 /*163 /*
161 * If user has specified capability overrides, take care164 * If user has specified capability overrides, take care
162 * of that if the station we're setting up is the AP that165 * of that if the station we're setting up is the AP that
net/wireless/chan.c+4−2
@@ -317,7 +317,7 @@ static bool cfg80211_valid_center_freq(u32 center, · 316 unmodified lines
317 int step;317 int step;
318 318
319 /* We only do strict verification on 6 GHz */319 /* We only do strict verification on 6 GHz */
320 if (center < 5955 || center > 7115)320 if (center < 5955 || center > 7215)
321 return true;321 return true;
322 322
323 bw = nl80211_chan_width_to_mhz(width);323 bw = nl80211_chan_width_to_mhz(width);
@@ -325,7 +325,7 @@ static bool cfg80211_valid_center_freq(u32 center, · 1 unmodified line
325 return false;325 return false;
326 326
327 /* Validate that the channels bw is entirely within the 6 GHz band */327 /* Validate that the channels bw is entirely within the 6 GHz band */
328 if (center - bw / 2 < 5945 || center + bw / 2 > 7125)328 if (center - bw / 2 < 5945 || center + bw / 2 > 7225)
329 return false;329 return false;
330 330
331 /* With 320 MHz the permitted channels overlap */331 /* With 320 MHz the permitted channels overlap */
@@ -816,6 +816,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, · 484 unmodified lines
816 case NL80211_IFTYPE_MONITOR:816 case NL80211_IFTYPE_MONITOR:
817 case NL80211_IFTYPE_AP_VLAN:817 case NL80211_IFTYPE_AP_VLAN:
818 case NL80211_IFTYPE_P2P_DEVICE:818 case NL80211_IFTYPE_P2P_DEVICE:
819 case NL80211_IFTYPE_NAN_DATA:
819 break;820 break;
820 case NL80211_IFTYPE_WDS:821 case NL80211_IFTYPE_WDS:
821 case NL80211_IFTYPE_UNSPECIFIED:822 case NL80211_IFTYPE_UNSPECIFIED:
@@ -939,6 +940,7 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) · 117 unmodified lines
939 case NL80211_IFTYPE_P2P_DEVICE:940 case NL80211_IFTYPE_P2P_DEVICE:
940 /* Can NAN type be considered as beaconing interface? */941 /* Can NAN type be considered as beaconing interface? */
941 case NL80211_IFTYPE_NAN:942 case NL80211_IFTYPE_NAN:
943 case NL80211_IFTYPE_NAN_DATA:
942 break;944 break;
943 case NL80211_IFTYPE_UNSPECIFIED:945 case NL80211_IFTYPE_UNSPECIFIED:
944 case NL80211_IFTYPE_WDS:946 case NL80211_IFTYPE_WDS:
net/wireless/core.c+120−10
@@ -5,7 +5,7 @@ · 4 unmodified lines
5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH6 * Copyright 2013-2014 Intel Mobile Communications GmbH
7 * Copyright 2015-2017 Intel Deutschland GmbH7 * Copyright 2015-2017 Intel Deutschland GmbH
8 * Copyright (C) 2018-2025 Intel Corporation8 * Copyright (C) 2018-2026 Intel Corporation
9 */9 */
10 10
11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -254,6 +254,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, · 242 unmodified lines
254void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,254void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
255 struct wireless_dev *wdev)255 struct wireless_dev *wdev)
256{256{
257 struct cfg80211_nan_local_sched empty_sched = {};
258
257 lockdep_assert_held(&rdev->wiphy.mtx);259 lockdep_assert_held(&rdev->wiphy.mtx);
258 260
259 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))261 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))
@@ -262,6 +264,15 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, · 2 unmodified lines
262 if (!wdev_running(wdev))264 if (!wdev_running(wdev))
263 return;265 return;
264 266
267 /*
268 * If there is a scheduled update pending, mark it as canceled, so the
269 * empty schedule will be accepted
270 */
271 wdev->u.nan.sched_update_pending = false;
272
273 /* Unschedule all */
274 cfg80211_nan_set_local_schedule(rdev, wdev, &empty_sched);
275
265 rdev_stop_nan(rdev, wdev);276 rdev_stop_nan(rdev, wdev);
266 wdev->is_running = false;277 wdev->is_running = false;
267 278
@@ -270,6 +281,47 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, · 2 unmodified lines
270 rdev->opencount--;281 rdev->opencount--;
271}282}
272 283
284int cfg80211_nan_set_local_schedule(struct cfg80211_registered_device *rdev,
285 struct wireless_dev *wdev,
286 struct cfg80211_nan_local_sched *sched)
287{
288 int ret;
289
290 lockdep_assert_held(&rdev->wiphy.mtx);
291
292 if (wdev->iftype != NL80211_IFTYPE_NAN || !wdev_running(wdev))
293 return -EINVAL;
294
295 if (wdev->u.nan.sched_update_pending)
296 return -EBUSY;
297
298 ret = rdev_nan_set_local_sched(rdev, wdev, sched);
299 if (ret)
300 return ret;
301
302 wdev->u.nan.sched_update_pending = sched->deferred;
303
304 kfree(wdev->u.nan.chandefs);
305 wdev->u.nan.chandefs = NULL;
306 wdev->u.nan.n_channels = 0;
307
308 if (!sched->n_channels)
309 return 0;
310
311 wdev->u.nan.chandefs = kcalloc(sched->n_channels,
312 sizeof(*wdev->u.nan.chandefs),
313 GFP_KERNEL);
314 if (!wdev->u.nan.chandefs)
315 return -ENOMEM;
316
317 for (int i = 0; i < sched->n_channels; i++)
318 wdev->u.nan.chandefs[i] = sched->nan_channels[i].chandef;
319
320 wdev->u.nan.n_channels = sched->n_channels;
321
322 return 0;
323}
324
273void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)325void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
274{326{
275 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);327 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -277,16 +329,21 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) · 1 unmodified line
277 329
278 ASSERT_RTNL();330 ASSERT_RTNL();
279 331
332 /*
333 * Some netdev interfaces need to be closed before some non-netdev
334 * ones, i.e. NAN_DATA interfaces need to be closed before the NAN
335 * interface
336 */
280 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {337 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
281 if (wdev->netdev) {338 if (wdev->netdev) {
282 dev_close(wdev->netdev);339 dev_close(wdev->netdev);
283 continue;340 continue;
284 }341 }
342 }
285 343
286 /* otherwise, check iftype */344 guard(wiphy)(wiphy);
287
288 guard(wiphy)(wiphy);
289 345
346 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
290 switch (wdev->iftype) {347 switch (wdev->iftype) {
291 case NL80211_IFTYPE_P2P_DEVICE:348 case NL80211_IFTYPE_P2P_DEVICE:
292 cfg80211_stop_p2p_device(rdev, wdev);349 cfg80211_stop_p2p_device(rdev, wdev);
@@ -344,6 +401,8 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) · 51 unmodified lines
344 401
345 list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {402 list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
346 if (wdev->nl_owner_dead) {403 if (wdev->nl_owner_dead) {
404 cfg80211_close_dependents(rdev, wdev);
405
347 if (wdev->netdev)406 if (wdev->netdev)
348 dev_close(wdev->netdev);407 dev_close(wdev->netdev);
349 408
@@ -354,6 +413,21 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) · 4 unmodified lines
354 }413 }
355}414}
356 415
416void cfg80211_close_dependents(struct cfg80211_registered_device *rdev,
417 struct wireless_dev *wdev)
418{
419 ASSERT_RTNL();
420
421 if (wdev->iftype != NL80211_IFTYPE_NAN)
422 return;
423
424 /* Close all NAN DATA interfaces */
425 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
426 if (wdev->iftype == NL80211_IFTYPE_NAN_DATA)
427 dev_close(wdev->netdev);
428 }
429}
430
357static void cfg80211_destroy_iface_wk(struct work_struct *work)431static void cfg80211_destroy_iface_wk(struct work_struct *work)
358{432{
359 struct cfg80211_registered_device *rdev;433 struct cfg80211_registered_device *rdev;
@@ -761,6 +835,10 @@ int wiphy_register(struct wiphy *wiphy) · 401 unmodified lines
761 !(wiphy->nan_supported_bands & BIT(NL80211_BAND_2GHZ)))))835 !(wiphy->nan_supported_bands & BIT(NL80211_BAND_2GHZ)))))
762 return -EINVAL;836 return -EINVAL;
763 837
838 if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN_DATA)) &&
839 !wiphy->nan_capa.phy.ht.ht_supported))
840 return -EINVAL;
841
764 if (WARN_ON(wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS)))842 if (WARN_ON(wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS)))
765 return -EINVAL;843 return -EINVAL;
766 844
@@ -1367,9 +1445,8 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, · 600 unmodified lines
1367 rdev->num_running_monitor_ifaces += num;1445 rdev->num_running_monitor_ifaces += num;
1368}1446}
1369 1447
1370void cfg80211_leave(struct cfg80211_registered_device *rdev,1448void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
1371 struct wireless_dev *wdev,1449 struct wireless_dev *wdev, int link_id)
1372 int link_id)
1373{1450{
1374 struct net_device *dev = wdev->netdev;1451 struct net_device *dev = wdev->netdev;
1375 struct cfg80211_sched_scan_request *pos, *tmp;1452 struct cfg80211_sched_scan_request *pos, *tmp;
@@ -1420,6 +1497,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, · 44 unmodified lines
1420 break;1497 break;
1421 case NL80211_IFTYPE_AP_VLAN:1498 case NL80211_IFTYPE_AP_VLAN:
1422 case NL80211_IFTYPE_MONITOR:1499 case NL80211_IFTYPE_MONITOR:
1500 case NL80211_IFTYPE_NAN_DATA:
1423 /* nothing to do */1501 /* nothing to do */
1424 break;1502 break;
1425 case NL80211_IFTYPE_UNSPECIFIED:1503 case NL80211_IFTYPE_UNSPECIFIED:
@@ -1430,6 +1508,19 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, · 4 unmodified lines
1430 }1508 }
1431}1509}
1432 1510
1511void cfg80211_leave(struct cfg80211_registered_device *rdev,
1512 struct wireless_dev *wdev, int link_id)
1513{
1514 ASSERT_RTNL();
1515
1516 /* NAN_DATA interfaces must be closed before stopping NAN */
1517 cfg80211_close_dependents(rdev, wdev);
1518
1519 guard(wiphy)(&rdev->wiphy);
1520
1521 cfg80211_leave_locked(rdev, wdev, link_id);
1522}
1523
1433void cfg80211_stop_link(struct wiphy *wiphy, struct wireless_dev *wdev,1524void cfg80211_stop_link(struct wiphy *wiphy, struct wireless_dev *wdev,
1434 int link_id, gfp_t gfp)1525 int link_id, gfp_t gfp)
1435{1526{
@@ -1445,6 +1536,9 @@ void cfg80211_stop_link(struct wiphy *wiphy, struct wireless_dev *wdev, · 9 unmodified lines
1445 1536
1446 trace_cfg80211_stop_link(wiphy, wdev, link_id);1537 trace_cfg80211_stop_link(wiphy, wdev, link_id);
1447 1538
1539 if (wdev->iftype == NL80211_IFTYPE_NAN)
1540 return;
1541
1448 ev = kzalloc_obj(*ev, gfp);1542 ev = kzalloc_obj(*ev, gfp);
1449 if (!ev)1543 if (!ev)
1450 return;1544 return;
@@ -1595,10 +1689,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 144 unmodified lines
1595 }1689 }
1596 break;1690 break;
1597 case NETDEV_GOING_DOWN:1691 case NETDEV_GOING_DOWN:
1598 scoped_guard(wiphy, &rdev->wiphy) {1692 cfg80211_leave(rdev, wdev, -1);
1599 cfg80211_leave(rdev, wdev, -1);1693 scoped_guard(wiphy, &rdev->wiphy)
1600 cfg80211_remove_links(wdev);1694 cfg80211_remove_links(wdev);
1601 }
1602 /* since we just did cfg80211_leave() nothing to do there */1695 /* since we just did cfg80211_leave() nothing to do there */
1603 cancel_work_sync(&wdev->disconnect_wk);1696 cancel_work_sync(&wdev->disconnect_wk);
1604 cancel_work_sync(&wdev->pmsr_free_wk);1697 cancel_work_sync(&wdev->pmsr_free_wk);
@@ -1679,6 +1772,23 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 74 unmodified lines
1679 1772
1680 if (rfkill_blocked(rdev->wiphy.rfkill))1773 if (rfkill_blocked(rdev->wiphy.rfkill))
1681 return notifier_from_errno(-ERFKILL);1774 return notifier_from_errno(-ERFKILL);
1775
1776 /* NAN_DATA interfaces require a running NAN interface */
1777 if (wdev->iftype == NL80211_IFTYPE_NAN_DATA) {
1778 struct wireless_dev *iter;
1779 bool nan_started = false;
1780
1781 list_for_each_entry(iter, &rdev->wiphy.wdev_list, list) {
1782 if (iter->iftype == NL80211_IFTYPE_NAN &&
1783 wdev_running(iter)) {
1784 nan_started = true;
1785 break;
1786 }
1787 }
1788
1789 if (!nan_started)
1790 return notifier_from_errno(-ENOLINK);
1791 }
1682 break;1792 break;
1683 default:1793 default:
1684 return NOTIFY_DONE;1794 return NOTIFY_DONE;
net/wireless/core.h+10−0
@@ -318,6 +318,9 @@ void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, · 317 unmodified lines
318 318
319void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);319void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
320 320
321void cfg80211_close_dependents(struct cfg80211_registered_device *rdev,
322 struct wireless_dev *wdev);
323
321/* free object */324/* free object */
322void cfg80211_dev_free(struct cfg80211_registered_device *rdev);325void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
323 326
@@ -541,6 +544,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, · 217 unmodified lines
541void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,544void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
542 enum nl80211_iftype iftype, int num);545 enum nl80211_iftype iftype, int num);
543 546
547void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
548 struct wireless_dev *wdev, int link_id);
549
544void cfg80211_leave(struct cfg80211_registered_device *rdev,550void cfg80211_leave(struct cfg80211_registered_device *rdev,
545 struct wireless_dev *wdev,551 struct wireless_dev *wdev,
546 int link_id);552 int link_id);
@@ -551,6 +557,10 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, · 4 unmodified lines
551void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,557void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
552 struct wireless_dev *wdev);558 struct wireless_dev *wdev);
553 559
560int cfg80211_nan_set_local_schedule(struct cfg80211_registered_device *rdev,
561 struct wireless_dev *wdev,
562 struct cfg80211_nan_local_sched *sched);
563
554struct cfg80211_internal_bss *564struct cfg80211_internal_bss *
555cfg80211_bss_update(struct cfg80211_registered_device *rdev,565cfg80211_bss_update(struct cfg80211_registered_device *rdev,
556 struct cfg80211_internal_bss *tmp,566 struct cfg80211_internal_bss *tmp,
net/wireless/mlme.c+9−4
@@ -4,7 +4,7 @@ · 3 unmodified lines
4 *4 *
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6 * Copyright (c) 2015 Intel Deutschland GmbH6 * Copyright (c) 2015 Intel Deutschland GmbH
7 * Copyright (C) 2019-2020, 2022-2025 Intel Corporation7 * Copyright (C) 2019-2020, 2022-2026 Intel Corporation
8 */8 */
9 9
10#include <linux/kernel.h>10#include <linux/kernel.h>
@@ -782,8 +782,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 771 unmodified lines
782 rdev_crit_proto_stop(rdev, wdev);782 rdev_crit_proto_stop(rdev, wdev);
783 }783 }
784 784
785 if (nlportid == wdev->ap_unexpected_nlportid)785 if (nlportid == wdev->unexpected_nlportid)
786 wdev->ap_unexpected_nlportid = 0;786 wdev->unexpected_nlportid = 0;
787}787}
788 788
789void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)789void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
@@ -933,12 +933,17 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, · 143 unmodified lines
933 * cfg80211 doesn't track the stations933 * cfg80211 doesn't track the stations
934 */934 */
935 break;935 break;
936 case NL80211_IFTYPE_NAN:
937 case NL80211_IFTYPE_NAN_DATA:
938 if (mgmt->u.action.category !=
939 WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION)
940 err = -EOPNOTSUPP;
941 break;
936 case NL80211_IFTYPE_P2P_DEVICE:942 case NL80211_IFTYPE_P2P_DEVICE:
937 /*943 /*
938 * fall through, P2P device only supports944 * fall through, P2P device only supports
939 * public action frames945 * public action frames
940 */946 */
941 case NL80211_IFTYPE_NAN:
942 default:947 default:
943 err = -EOPNOTSUPP;948 err = -EOPNOTSUPP;
944 break;949 break;
net/wireless/nl80211.c+877−28
@@ -333,6 +333,97 @@ static int validate_nan_cluster_id(const struct nlattr *attr, · 332 unmodified lines
333 return 0;333 return 0;
334}334}
335 335
336static int validate_nan_avail_blob(const struct nlattr *attr,
337 struct netlink_ext_ack *extack)
338{
339 const u8 *data = nla_data(attr);
340 unsigned int len = nla_len(attr);
341 u16 attr_len;
342
343 /* Need at least: Attr ID (1) + Length (2) */
344 if (len < 3) {
345 NL_SET_ERR_MSG_FMT(extack,
346 "NAN Availability: Too short (need at least 3 bytes, have %u)",
347 len);
348 return -EINVAL;
349 }
350
351 if (data[0] != 0x12) {
352 NL_SET_ERR_MSG_FMT(extack,
353 "NAN Availability: Invalid Attribute ID 0x%02x (expected 0x12)",
354 data[0]);
355 return -EINVAL;
356 }
357
358 attr_len = get_unaligned_le16(&data[1]);
359
360 if (attr_len != len - 3) {
361 NL_SET_ERR_MSG_FMT(extack,
362 "NAN Availability: Length field (%u) doesn't match data length (%u)",
363 attr_len, len - 3);
364 return -EINVAL;
365 }
366
367 return 0;
368}
369
370static int validate_nan_ulw(const struct nlattr *attr,
371 struct netlink_ext_ack *extack)
372{
373 const u8 *data = nla_data(attr);
374 unsigned int len = nla_len(attr);
375 unsigned int pos = 0;
376
377 while (pos < len) {
378 u16 attr_len;
379
380 /* Need at least: Attr ID (1) + Length (2) */
381 if (pos + 3 > len) {
382 NL_SET_ERR_MSG_FMT(extack,
383 "ULW: Incomplete header (need 3 bytes, have %u)",
384 len - pos);
385 return -EINVAL;
386 }
387
388 if (data[pos] != 0x17) {
389 NL_SET_ERR_MSG_FMT(extack,
390 "ULW: Invalid Attribute ID 0x%02x (expected 0x17)",
391 data[pos]);
392 return -EINVAL;
393 }
394 pos++;
395
396 /* Length is in little-endian format */
397 attr_len = get_unaligned_le16(&data[pos]);
398 pos += 2;
399
400 /*
401 * Check if length is one of the valid values: 16 (no
402 * channel/band entry included), 18 (band entry included),
403 * 21 (channel entry included without Auxiliary channel bitmap),
404 * or 23 (channel entry included with Auxiliary channel bitmap).
405 */
406 if (attr_len != 16 && attr_len != 18 && attr_len != 21 &&
407 attr_len != 23) {
408 NL_SET_ERR_MSG_FMT(extack,
409 "ULW: Invalid length %u (must be 16, 18, 21, or 23)",
410 attr_len);
411 return -EINVAL;
412 }
413
414 if (pos + attr_len > len) {
415 NL_SET_ERR_MSG_FMT(extack,
416 "ULW: Length field (%u) exceeds remaining data (%u)",
417 attr_len, len - pos);
418 return -EINVAL;
419 }
420
421 pos += attr_len;
422 }
423
424 return 0;
425}
426
336static int validate_uhr_capa(const struct nlattr *attr,427static int validate_uhr_capa(const struct nlattr *attr,
337 struct netlink_ext_ack *extack)428 struct netlink_ext_ack *extack)
338{429{
@@ -555,6 +646,13 @@ nl80211_nan_band_conf_policy[NL80211_NAN_BAND_CONF_ATTR_MAX + 1] = { · 216 unmodified lines
555 [NL80211_NAN_BAND_CONF_DISABLE_SCAN] = { .type = NLA_FLAG },646 [NL80211_NAN_BAND_CONF_DISABLE_SCAN] = { .type = NLA_FLAG },
556};647};
557 648
649static const struct nla_policy
650nl80211_nan_peer_map_policy[NL80211_NAN_PEER_MAP_ATTR_MAX + 1] = {
651 [NL80211_NAN_PEER_MAP_ATTR_MAP_ID] = NLA_POLICY_MAX(NLA_U8, 15),
652 [NL80211_NAN_PEER_MAP_ATTR_TIME_SLOTS] =
653 NLA_POLICY_EXACT_LEN(CFG80211_NAN_SCHED_NUM_TIME_SLOTS),
654};
655
558static const struct nla_policy656static const struct nla_policy
559nl80211_nan_conf_policy[NL80211_NAN_CONF_ATTR_MAX + 1] = {657nl80211_nan_conf_policy[NL80211_NAN_CONF_ATTR_MAX + 1] = {
560 [NL80211_NAN_CONF_CLUSTER_ID] =658 [NL80211_NAN_CONF_CLUSTER_ID] =
@@ -962,6 +1060,22 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 401 unmodified lines
962 [NL80211_ATTR_DISABLE_UHR] = { .type = NLA_FLAG },1060 [NL80211_ATTR_DISABLE_UHR] = { .type = NLA_FLAG },
963 [NL80211_ATTR_UHR_OPERATION] =1061 [NL80211_ATTR_UHR_OPERATION] =
964 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_uhr_operation),1062 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_uhr_operation),
1063 [NL80211_ATTR_NAN_CHANNEL] = NLA_POLICY_NESTED(nl80211_policy),
1064 [NL80211_ATTR_NAN_CHANNEL_ENTRY] = NLA_POLICY_EXACT_LEN(6),
1065 [NL80211_ATTR_NAN_RX_NSS] = { .type = NLA_U8 },
1066 [NL80211_ATTR_NAN_TIME_SLOTS] =
1067 NLA_POLICY_EXACT_LEN(CFG80211_NAN_SCHED_NUM_TIME_SLOTS),
1068 [NL80211_ATTR_NAN_AVAIL_BLOB] =
1069 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_nan_avail_blob),
1070 [NL80211_ATTR_NAN_SCHED_DEFERRED] = { .type = NLA_FLAG },
1071 [NL80211_ATTR_NAN_NMI_MAC] = NLA_POLICY_ETH_ADDR,
1072 [NL80211_ATTR_NAN_ULW] =
1073 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_nan_ulw),
1074 [NL80211_ATTR_NAN_COMMITTED_DW] = { .type = NLA_U16 },
1075 [NL80211_ATTR_NAN_SEQ_ID] = { .type = NLA_U8 },
1076 [NL80211_ATTR_NAN_MAX_CHAN_SWITCH_TIME] = { .type = NLA_U16 },
1077 [NL80211_ATTR_NAN_PEER_MAPS] =
1078 NLA_POLICY_NESTED_ARRAY(nl80211_nan_peer_map_policy),
965};1079};
966 1080
967/* policy for the key attributes */1081/* policy for the key attributes */
@@ -1722,6 +1836,7 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) · 754 unmodified lines
1722 return 0;1836 return 0;
1723 return -ENOLINK;1837 return -ENOLINK;
1724 case NL80211_IFTYPE_NAN:1838 case NL80211_IFTYPE_NAN:
1839 case NL80211_IFTYPE_NAN_DATA:
1725 if (wiphy_ext_feature_isset(wdev->wiphy,1840 if (wiphy_ext_feature_isset(wdev->wiphy,
1726 NL80211_EXT_FEATURE_SECURE_NAN))1841 NL80211_EXT_FEATURE_SECURE_NAN))
1727 return 0;1842 return 0;
@@ -2678,6 +2793,68 @@ fail: · 950 unmodified lines
2678 return -ENOBUFS;2793 return -ENOBUFS;
2679}2794}
2680 2795
2796static int nl80211_put_nan_phy_cap(struct wiphy *wiphy, struct sk_buff *msg)
2797{
2798 struct nlattr *nl_phy_cap;
2799 const struct ieee80211_sta_ht_cap *ht_cap;
2800 const struct ieee80211_sta_vht_cap *vht_cap;
2801 const struct ieee80211_sta_he_cap *he_cap;
2802
2803 if (!cfg80211_iftype_allowed(wiphy, NL80211_IFTYPE_NAN_DATA, false, 0))
2804 return 0;
2805
2806 ht_cap = &wiphy->nan_capa.phy.ht;
2807 vht_cap = &wiphy->nan_capa.phy.vht;
2808 he_cap = &wiphy->nan_capa.phy.he;
2809
2810 /* HT is mandatory */
2811 if (WARN_ON(!ht_cap->ht_supported))
2812 return 0;
2813
2814 nl_phy_cap = nla_nest_start_noflag(msg, NL80211_NAN_CAPA_PHY);
2815 if (!nl_phy_cap)
2816 return -ENOBUFS;
2817
2818 if (nla_put(msg, NL80211_NAN_PHY_CAP_ATTR_HT_MCS_SET,
2819 sizeof(ht_cap->mcs), &ht_cap->mcs) ||
2820 nla_put_u16(msg, NL80211_NAN_PHY_CAP_ATTR_HT_CAPA, ht_cap->cap) ||
2821 nla_put_u8(msg, NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_FACTOR,
2822 ht_cap->ampdu_factor) ||
2823 nla_put_u8(msg, NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_DENSITY,
2824 ht_cap->ampdu_density))
2825 goto fail;
2826
2827 if (vht_cap->vht_supported) {
2828 if (nla_put(msg, NL80211_NAN_PHY_CAP_ATTR_VHT_MCS_SET,
2829 sizeof(vht_cap->vht_mcs), &vht_cap->vht_mcs) ||
2830 nla_put_u32(msg, NL80211_NAN_PHY_CAP_ATTR_VHT_CAPA,
2831 vht_cap->cap))
2832 goto fail;
2833 }
2834
2835 if (he_cap->has_he) {
2836 if (nla_put(msg, NL80211_NAN_PHY_CAP_ATTR_HE_MAC,
2837 sizeof(he_cap->he_cap_elem.mac_cap_info),
2838 he_cap->he_cap_elem.mac_cap_info) ||
2839 nla_put(msg, NL80211_NAN_PHY_CAP_ATTR_HE_PHY,
2840 sizeof(he_cap->he_cap_elem.phy_cap_info),
2841 he_cap->he_cap_elem.phy_cap_info) ||
2842 nla_put(msg, NL80211_NAN_PHY_CAP_ATTR_HE_MCS_SET,
2843 sizeof(he_cap->he_mcs_nss_supp),
2844 &he_cap->he_mcs_nss_supp) ||
2845 nla_put(msg, NL80211_NAN_PHY_CAP_ATTR_HE_PPE,
2846 sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
2847 goto fail;
2848 }
2849
2850 nla_nest_end(msg, nl_phy_cap);
2851 return 0;
2852
2853fail:
2854 nla_nest_cancel(msg, nl_phy_cap);
2855 return -ENOBUFS;
2856}
2857
2681static int nl80211_put_nan_capa(struct wiphy *wiphy, struct sk_buff *msg)2858static int nl80211_put_nan_capa(struct wiphy *wiphy, struct sk_buff *msg)
2682{2859{
2683 struct nlattr *nan_caps;2860 struct nlattr *nan_caps;
@@ -2704,6 +2881,9 @@ static int nl80211_put_nan_capa(struct wiphy *wiphy, struct sk_buff *msg) · 20 unmodified lines
2704 wiphy->nan_capa.dev_capabilities))2881 wiphy->nan_capa.dev_capabilities))
2705 goto fail;2882 goto fail;
2706 2883
2884 if (nl80211_put_nan_phy_cap(wiphy, msg))
2885 goto fail;
2886
2707 nla_nest_end(msg, nan_caps);2887 nla_nest_end(msg, nan_caps);
2708 2888
2709 return 0;2889 return 0;
@@ -4879,6 +5059,8 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) · 2169 unmodified lines
4879 else5059 else
4880 dev_close(wdev->netdev);5060 dev_close(wdev->netdev);
4881 5061
5062 cfg80211_close_dependents(rdev, wdev);
5063
4882 mutex_lock(&rdev->wiphy.mtx);5064 mutex_lock(&rdev->wiphy.mtx);
4883 5065
4884 return cfg80211_remove_virtual_intf(rdev, wdev);5066 return cfg80211_remove_virtual_intf(rdev, wdev);
@@ -7123,6 +7305,26 @@ static int parse_station_flags(struct genl_info *info, · 2238 unmodified lines
7123 if ((params->sta_flags_mask |7305 if ((params->sta_flags_mask |
7124 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))7306 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
7125 return -EINVAL;7307 return -EINVAL;
7308
7309 if ((iftype == NL80211_IFTYPE_NAN ||
7310 iftype == NL80211_IFTYPE_NAN_DATA) &&
7311 params->sta_flags_mask &
7312 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
7313 BIT(NL80211_STA_FLAG_ASSOCIATED) |
7314 BIT(NL80211_STA_FLAG_AUTHORIZED) |
7315 BIT(NL80211_STA_FLAG_MFP)))
7316 return -EINVAL;
7317
7318 /* WME is always used in NAN */
7319 if (iftype == NL80211_IFTYPE_NAN_DATA) {
7320 /* but don't let userspace control it */
7321 if (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))
7322 return -EINVAL;
7323
7324 params->sta_flags_mask |= BIT(NL80211_STA_FLAG_WME);
7325 params->sta_flags_set |= BIT(NL80211_STA_FLAG_WME);
7326 }
7327
7126 return 0;7328 return 0;
7127 }7329 }
7128 7330
@@ -8005,7 +8207,7 @@ static int nl80211_dump_station(struct sk_buff *skb, · 876 unmodified lines
8005 /* nl80211_prepare_wdev_dump acquired it in the successful case */8207 /* nl80211_prepare_wdev_dump acquired it in the successful case */
8006 __acquire(&rdev->wiphy.mtx);8208 __acquire(&rdev->wiphy.mtx);
8007 8209
8008 if (!wdev->netdev) {8210 if (!wdev->netdev && wdev->iftype != NL80211_IFTYPE_NAN) {
8009 err = -EINVAL;8211 err = -EINVAL;
8010 goto out_err;8212 goto out_err;
8011 }8213 }
@@ -8192,10 +8394,12 @@ int cfg80211_check_station_change(struct wiphy *wiphy, · 180 unmodified lines
8192 return -EINVAL;8394 return -EINVAL;
8193 if (params->link_sta_params.supported_rates)8395 if (params->link_sta_params.supported_rates)
8194 return -EINVAL;8396 return -EINVAL;
8195 if (params->ext_capab || params->link_sta_params.ht_capa ||8397 if (statype != CFG80211_STA_NAN_MGMT &&
8196 params->link_sta_params.vht_capa ||8398 (params->link_sta_params.ht_capa ||
8197 params->link_sta_params.he_capa ||8399 params->link_sta_params.vht_capa ||
8198 params->link_sta_params.eht_capa ||8400 params->link_sta_params.he_capa))
8401 return -EINVAL;
8402 if (params->ext_capab || params->link_sta_params.eht_capa ||
8199 params->link_sta_params.uhr_capa)8403 params->link_sta_params.uhr_capa)
8200 return -EINVAL;8404 return -EINVAL;
8201 if (params->sta_flags_mask & BIT(NL80211_STA_FLAG_SPP_AMSDU))8405 if (params->sta_flags_mask & BIT(NL80211_STA_FLAG_SPP_AMSDU))
@@ -8267,6 +8471,19 @@ int cfg80211_check_station_change(struct wiphy *wiphy, · 65 unmodified lines
8267 params->plink_action != NL80211_PLINK_ACTION_BLOCK)8471 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
8268 return -EINVAL;8472 return -EINVAL;
8269 break;8473 break;
8474 case CFG80211_STA_NAN_MGMT:
8475 if (params->sta_flags_mask &
8476 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
8477 BIT(NL80211_STA_FLAG_MFP)))
8478 return -EINVAL;
8479 break;
8480 case CFG80211_STA_NAN_DATA:
8481 if (params->sta_flags_mask &
8482 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
8483 BIT(NL80211_STA_FLAG_MFP) |
8484 BIT(NL80211_STA_FLAG_WME)))
8485 return -EINVAL;
8486 break;
8270 }8487 }
8271 8488
8272 /*8489 /*
@@ -8481,7 +8698,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 208 unmodified lines
8481 8698
8482 memset(&params, 0, sizeof(params));8699 memset(&params, 0, sizeof(params));
8483 8700
8484 if (!dev)8701 if (!dev && wdev->iftype != NL80211_IFTYPE_NAN &&
8702 wdev->iftype != NL80211_IFTYPE_NAN_DATA)
8485 return -EINVAL;8703 return -EINVAL;
8486 8704
8487 if (!rdev->ops->change_station)8705 if (!rdev->ops->change_station)
@@ -8624,6 +8842,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 136 unmodified lines
8624 case NL80211_IFTYPE_STATION:8842 case NL80211_IFTYPE_STATION:
8625 case NL80211_IFTYPE_ADHOC:8843 case NL80211_IFTYPE_ADHOC:
8626 case NL80211_IFTYPE_MESH_POINT:8844 case NL80211_IFTYPE_MESH_POINT:
8845 case NL80211_IFTYPE_NAN:
8846 case NL80211_IFTYPE_NAN_DATA:
8627 break;8847 break;
8628 default:8848 default:
8629 err = -EOPNOTSUPP;8849 err = -EOPNOTSUPP;
@@ -8652,7 +8872,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 22 unmodified lines
8652 8872
8653 memset(&params, 0, sizeof(params));8873 memset(&params, 0, sizeof(params));
8654 8874
8655 if (!dev)8875 if (!dev && wdev->iftype != NL80211_IFTYPE_NAN)
8656 return -EINVAL;8876 return -EINVAL;
8657 8877
8658 if (!rdev->ops->add_station)8878 if (!rdev->ops->add_station)
@@ -8661,15 +8881,31 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 2 unmodified lines
8661 if (!info->attrs[NL80211_ATTR_MAC])8881 if (!info->attrs[NL80211_ATTR_MAC])
8662 return -EINVAL;8882 return -EINVAL;
8663 8883
8664 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])8884 if (wdev->iftype == NL80211_IFTYPE_NAN ||
8665 return -EINVAL;8885 wdev->iftype == NL80211_IFTYPE_NAN_DATA) {
8886 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
8887 return -EINVAL;
8888 if (wdev->iftype == NL80211_IFTYPE_NAN_DATA) {
8889 if (!info->attrs[NL80211_ATTR_NAN_NMI_MAC])
8890 return -EINVAL;
8666 8891
8667 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])8892 /* Only NMI stations receive the HT/VHT/HE capabilities */
8668 return -EINVAL;8893 if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
8894 info->attrs[NL80211_ATTR_VHT_CAPABILITY] ||
8895 info->attrs[NL80211_ATTR_HE_CAPABILITY])
8896 return -EINVAL;
8897 }
8898 } else {
8899 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
8900 return -EINVAL;
8669 8901
8670 if (!info->attrs[NL80211_ATTR_STA_AID] &&8902 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
8671 !info->attrs[NL80211_ATTR_PEER_AID])8903 return -EINVAL;
8672 return -EINVAL;8904
8905 if (!info->attrs[NL80211_ATTR_STA_AID] &&
8906 !info->attrs[NL80211_ATTR_PEER_AID])
8907 return -EINVAL;
8908 }
8673 8909
8674 params.link_sta_params.link_id =8910 params.link_sta_params.link_id =
8675 nl80211_link_id_or_invalid(info->attrs);8911 nl80211_link_id_or_invalid(info->attrs);
@@ -8685,12 +8921,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 9 unmodified lines
8685 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);8921 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
8686 }8922 }
8687 8923
8688 params.link_sta_params.supported_rates =8924 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
8689 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);8925 params.link_sta_params.supported_rates =
8690 params.link_sta_params.supported_rates_len =8926 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
8691 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);8927 params.link_sta_params.supported_rates_len =
8692 params.listen_interval =8928 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
8693 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);8929 }
8930
8931 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
8932 params.listen_interval =
8933 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
8694 8934
8695 if (info->attrs[NL80211_ATTR_VLAN_ID])8935 if (info->attrs[NL80211_ATTR_VLAN_ID])
8696 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);8936 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
@@ -8709,7 +8949,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 12 unmodified lines
8709 8949
8710 if (info->attrs[NL80211_ATTR_PEER_AID])8950 if (info->attrs[NL80211_ATTR_PEER_AID])
8711 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);8951 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
8712 else8952 else if (info->attrs[NL80211_ATTR_STA_AID])
8713 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);8953 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
8714 8954
8715 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {8955 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
@@ -8830,6 +9070,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 114 unmodified lines
8830 return -EINVAL;9070 return -EINVAL;
8831 }9071 }
8832 9072
9073 if (wdev->iftype == NL80211_IFTYPE_NAN ||
9074 wdev->iftype == NL80211_IFTYPE_NAN_DATA) {
9075 if (params.sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
9076 return -EINVAL;
9077 /* NAN NMI station must be added in associated or authorized state */
9078 if (!(params.sta_flags_set & (BIT(NL80211_STA_FLAG_ASSOCIATED) |
9079 BIT(NL80211_STA_FLAG_AUTHENTICATED))))
9080 return -EINVAL;
9081 }
9082
8833 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */9083 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
8834 if (params.link_sta_params.he_6ghz_capa &&9084 if (params.link_sta_params.he_6ghz_capa &&
8835 (params.link_sta_params.ht_capa || params.link_sta_params.vht_capa))9085 (params.link_sta_params.ht_capa || params.link_sta_params.vht_capa))
@@ -8922,6 +9172,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 86 unmodified lines
8922 */9172 */
8923 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);9173 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
8924 break;9174 break;
9175 case NL80211_IFTYPE_NAN:
9176 break;
9177 case NL80211_IFTYPE_NAN_DATA:
9178 params.nmi_mac = nla_data(info->attrs[NL80211_ATTR_NAN_NMI_MAC]);
9179 break;
8925 default:9180 default:
8926 return -EOPNOTSUPP;9181 return -EOPNOTSUPP;
8927 }9182 }
@@ -8963,7 +9218,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) · 35 unmodified lines
8963 9218
8964 memset(&params, 0, sizeof(params));9219 memset(&params, 0, sizeof(params));
8965 9220
8966 if (!dev)9221 if (!dev && wdev->iftype != NL80211_IFTYPE_NAN)
8967 return -EINVAL;9222 return -EINVAL;
8968 9223
8969 if (info->attrs[NL80211_ATTR_MAC])9224 if (info->attrs[NL80211_ATTR_MAC])
@@ -8974,6 +9229,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) · 4 unmodified lines
8974 case NL80211_IFTYPE_AP_VLAN:9229 case NL80211_IFTYPE_AP_VLAN:
8975 case NL80211_IFTYPE_MESH_POINT:9230 case NL80211_IFTYPE_MESH_POINT:
8976 case NL80211_IFTYPE_P2P_GO:9231 case NL80211_IFTYPE_P2P_GO:
9232 case NL80211_IFTYPE_NAN:
9233 case NL80211_IFTYPE_NAN_DATA:
8977 /* always accept these */9234 /* always accept these */
8978 break;9235 break;
8979 case NL80211_IFTYPE_ADHOC:9236 case NL80211_IFTYPE_ADHOC:
@@ -13950,6 +14207,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) · 4970 unmodified lines
13950 case NL80211_IFTYPE_P2P_DEVICE:14207 case NL80211_IFTYPE_P2P_DEVICE:
13951 break;14208 break;
13952 case NL80211_IFTYPE_NAN:14209 case NL80211_IFTYPE_NAN:
14210 case NL80211_IFTYPE_NAN_DATA:
13953 if (!wiphy_ext_feature_isset(wdev->wiphy,14211 if (!wiphy_ext_feature_isset(wdev->wiphy,
13954 NL80211_EXT_FEATURE_SECURE_NAN) &&14212 NL80211_EXT_FEATURE_SECURE_NAN) &&
13955 !(wdev->wiphy->nan_capa.flags &14213 !(wdev->wiphy->nan_capa.flags &
@@ -14013,6 +14271,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) · 57 unmodified lines
14013 case NL80211_IFTYPE_P2P_GO:14271 case NL80211_IFTYPE_P2P_GO:
14014 break;14272 break;
14015 case NL80211_IFTYPE_NAN:14273 case NL80211_IFTYPE_NAN:
14274 case NL80211_IFTYPE_NAN_DATA:
14016 if (!wiphy_ext_feature_isset(wdev->wiphy,14275 if (!wiphy_ext_feature_isset(wdev->wiphy,
14017 NL80211_EXT_FEATURE_SECURE_NAN) &&14276 NL80211_EXT_FEATURE_SECURE_NAN) &&
14018 !(wdev->wiphy->nan_capa.flags &14277 !(wdev->wiphy->nan_capa.flags &
@@ -15520,13 +15779,14 @@ static int nl80211_register_unexpected_frame(struct sk_buff *skb, · 1501 unmodified lines
15520 struct wireless_dev *wdev = dev->ieee80211_ptr;15779 struct wireless_dev *wdev = dev->ieee80211_ptr;
15521 15780
15522 if (wdev->iftype != NL80211_IFTYPE_AP &&15781 if (wdev->iftype != NL80211_IFTYPE_AP &&
15523 wdev->iftype != NL80211_IFTYPE_P2P_GO)15782 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
15783 wdev->iftype != NL80211_IFTYPE_NAN_DATA)
15524 return -EINVAL;15784 return -EINVAL;
15525 15785
15526 if (wdev->ap_unexpected_nlportid)15786 if (wdev->unexpected_nlportid)
15527 return -EBUSY;15787 return -EBUSY;
15528 15788
15529 wdev->ap_unexpected_nlportid = info->snd_portid;15789 wdev->unexpected_nlportid = info->snd_portid;
15530 return 0;15790 return 0;
15531}15791}
15532 15792
@@ -15922,6 +16182,10 @@ static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info) · 389 unmodified lines
15922 if (wdev->iftype != NL80211_IFTYPE_NAN)16182 if (wdev->iftype != NL80211_IFTYPE_NAN)
15923 return -EOPNOTSUPP;16183 return -EOPNOTSUPP;
15924 16184
16185 cfg80211_close_dependents(rdev, wdev);
16186
16187 guard(wiphy)(&rdev->wiphy);
16188
15925 cfg80211_stop_nan(rdev, wdev);16189 cfg80211_stop_nan(rdev, wdev);
15926 16190
15927 return 0;16191 return 0;
@@ -16421,6 +16685,482 @@ nla_put_failure: · 493 unmodified lines
16421}16685}
16422EXPORT_SYMBOL(cfg80211_nan_func_terminated);16686EXPORT_SYMBOL(cfg80211_nan_func_terminated);
16423 16687
16688void cfg80211_nan_sched_update_done(struct wireless_dev *wdev, bool success,
16689 gfp_t gfp)
16690{
16691 struct wiphy *wiphy = wdev->wiphy;
16692 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
16693 struct sk_buff *msg;
16694 void *hdr;
16695
16696 trace_cfg80211_nan_sched_update_done(wiphy, wdev, success);
16697
16698 /* Can happen if we stopped NAN */
16699 if (!wdev->u.nan.sched_update_pending)
16700 return;
16701
16702 wdev->u.nan.sched_update_pending = false;
16703
16704 if (!wdev->owner_nlportid)
16705 return;
16706
16707 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
16708 if (!msg)
16709 return;
16710
16711 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_SCHED_UPDATE_DONE);
16712 if (!hdr)
16713 goto nla_put_failure;
16714
16715 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16716 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16717 NL80211_ATTR_PAD) ||
16718 (success &&
16719 nla_put_flag(msg, NL80211_ATTR_NAN_SCHED_UPDATE_SUCCESS)))
16720 goto nla_put_failure;
16721
16722 genlmsg_end(msg, hdr);
16723
16724 genlmsg_unicast(wiphy_net(wiphy), msg, wdev->owner_nlportid);
16725
16726 return;
16727
16728nla_put_failure:
16729 nlmsg_free(msg);
16730}
16731EXPORT_SYMBOL(cfg80211_nan_sched_update_done);
16732
16733static int nl80211_parse_nan_channel(struct cfg80211_registered_device *rdev,
16734 struct nlattr *channel,
16735 struct genl_info *info,
16736 struct cfg80211_nan_channel *nan_channels,
16737 u8 index, bool local)
16738{
16739 struct nlattr **channel_parsed __free(kfree) = NULL;
16740 struct cfg80211_chan_def chandef;
16741 u8 n_rx_nss;
16742 int ret;
16743
16744 channel_parsed = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*channel_parsed),
16745 GFP_KERNEL);
16746 if (!channel_parsed)
16747 return -ENOMEM;
16748
16749 ret = nla_parse_nested(channel_parsed, NL80211_ATTR_MAX, channel, NULL,
16750 info->extack);
16751 if (ret)
16752 return ret;
16753
16754 ret = nl80211_parse_chandef(rdev, info->extack, channel_parsed,
16755 &chandef);
16756 if (ret)
16757 return ret;
16758
16759 if (chandef.chan->band == NL80211_BAND_6GHZ) {
16760 NL_SET_ERR_MSG(info->extack,
16761 "6 GHz band is not supported");
16762 return -EOPNOTSUPP;
16763 }
16764
16765 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef,
16766 NL80211_IFTYPE_NAN)) {
16767 NL_SET_ERR_MSG_ATTR(info->extack, channel,
16768 "Channel in NAN schedule is not allowed for NAN operation");
16769 return -EINVAL;
16770 }
16771
16772 if (local) {
16773 for (int i = 0; i < index; i++) {
16774 if (cfg80211_chandef_compatible(&nan_channels[i].chandef,
16775 &chandef)) {
16776 NL_SET_ERR_MSG_ATTR(info->extack, channel,
16777 "Channels in NAN schedule must be mutually incompatible");
16778 return -EINVAL;
16779 }
16780 }
16781 }
16782
16783 if (!channel_parsed[NL80211_ATTR_NAN_CHANNEL_ENTRY]) {
16784 NL_SET_ERR_MSG(info->extack,
16785 "Missing NAN channel entry attribute");
16786 return -EINVAL;
16787 }
16788
16789 nan_channels[index].channel_entry =
16790 nla_data(channel_parsed[NL80211_ATTR_NAN_CHANNEL_ENTRY]);
16791
16792 if (!channel_parsed[NL80211_ATTR_NAN_RX_NSS]) {
16793 NL_SET_ERR_MSG(info->extack,
16794 "Missing NAN RX NSS attribute");
16795 return -EINVAL;
16796 }
16797
16798 nan_channels[index].rx_nss =
16799 nla_get_u8(channel_parsed[NL80211_ATTR_NAN_RX_NSS]);
16800
16801 n_rx_nss = u8_get_bits(rdev->wiphy.nan_capa.n_antennas, 0x03);
16802 if ((local && nan_channels[index].rx_nss > n_rx_nss) ||
16803 !nan_channels[index].rx_nss) {
16804 NL_SET_ERR_MSG_ATTR(info->extack, channel,
16805 "Invalid RX NSS in NAN channel definition");
16806 return -EINVAL;
16807 }
16808
16809 nan_channels[index].chandef = chandef;
16810
16811 return 0;
16812}
16813
16814static int
16815nl80211_parse_nan_schedule(struct genl_info *info, struct nlattr *slots_attr,
16816 u8 schedule[CFG80211_NAN_SCHED_NUM_TIME_SLOTS],
16817 u8 n_channels)
16818{
16819 if (WARN_ON(nla_len(slots_attr) != CFG80211_NAN_SCHED_NUM_TIME_SLOTS))
16820 return -EINVAL;
16821
16822 memcpy(schedule, nla_data(slots_attr), nla_len(slots_attr));
16823
16824 for (int slot = 0; slot < CFG80211_NAN_SCHED_NUM_TIME_SLOTS; slot++) {
16825 if (schedule[slot] != NL80211_NAN_SCHED_NOT_AVAIL_SLOT &&
16826 schedule[slot] >= n_channels) {
16827 NL_SET_ERR_MSG_FMT(info->extack,
16828 "Invalid time slot: slot %d refers to channel index %d, n_channels=%d",
16829 slot, schedule[slot], n_channels);
16830 return -EINVAL;
16831 }
16832 }
16833
16834 return 0;
16835}
16836
16837static int
16838nl80211_parse_nan_peer_map(struct genl_info *info, struct nlattr *map_attr,
16839 struct cfg80211_nan_peer_map *map, u8 n_channels)
16840{
16841 struct nlattr *tb[NL80211_NAN_PEER_MAP_ATTR_MAX + 1];
16842 int ret;
16843
16844 ret = nla_parse_nested(tb, NL80211_NAN_PEER_MAP_ATTR_MAX, map_attr,
16845 nl80211_nan_peer_map_policy, info->extack);
16846 if (ret)
16847 return ret;
16848
16849 if (!tb[NL80211_NAN_PEER_MAP_ATTR_MAP_ID] ||
16850 !tb[NL80211_NAN_PEER_MAP_ATTR_TIME_SLOTS]) {
16851 NL_SET_ERR_MSG(info->extack,
16852 "Missing required peer map attributes");
16853 return -EINVAL;
16854 }
16855
16856 map->map_id = nla_get_u8(tb[NL80211_NAN_PEER_MAP_ATTR_MAP_ID]);
16857
16858 /* Parse schedule */
16859 return nl80211_parse_nan_schedule(info,
16860 tb[NL80211_NAN_PEER_MAP_ATTR_TIME_SLOTS],
16861 map->schedule, n_channels);
16862}
16863
16864static int nl80211_nan_validate_map_pair(struct wiphy *wiphy,
16865 struct genl_info *info,
16866 const struct cfg80211_nan_peer_map *map1,
16867 const struct cfg80211_nan_peer_map *map2,
16868 struct cfg80211_nan_channel *nan_channels)
16869{
16870 /* Check for duplicate map_id */
16871 if (map1->map_id == map2->map_id) {
16872 NL_SET_ERR_MSG_FMT(info->extack, "Duplicate map_id %u",
16873 map1->map_id);
16874 return -EINVAL;
16875 }
16876
16877 /* Check for compatible channels between maps */
16878 for (int i = 0; i < ARRAY_SIZE(map1->schedule); i++) {
16879 if (map1->schedule[i] == NL80211_NAN_SCHED_NOT_AVAIL_SLOT)
16880 continue;
16881
16882 for (int j = 0; j < ARRAY_SIZE(map2->schedule); j++) {
16883 u8 ch1 = map1->schedule[i];
16884 u8 ch2 = map2->schedule[j];
16885
16886 if (ch2 == NL80211_NAN_SCHED_NOT_AVAIL_SLOT)
16887 continue;
16888
16889 if (cfg80211_chandef_compatible(&nan_channels[ch1].chandef,
16890 &nan_channels[ch2].chandef)) {
16891 NL_SET_ERR_MSG_FMT(info->extack,
16892 "Maps %u and %u have compatible channels %d and %d",
16893 map1->map_id, map2->map_id,
16894 ch1, ch2);
16895 return -EINVAL;
16896 }
16897 }
16898 }
16899
16900 /*
16901 * Check for conflicting time slots between maps.
16902 * Only check for single-radio devices (n_radio <= 1) which cannot
16903 * operate on multiple channels simultaneously.
16904 */
16905 if (wiphy->n_radio > 1)
16906 return 0;
16907
16908 for (int i = 0; i < ARRAY_SIZE(map1->schedule); i++) {
16909 if (map1->schedule[i] != NL80211_NAN_SCHED_NOT_AVAIL_SLOT &&
16910 map2->schedule[i] != NL80211_NAN_SCHED_NOT_AVAIL_SLOT) {
16911 NL_SET_ERR_MSG_FMT(info->extack,
16912 "Maps %u and %u both schedule slot %d",
16913 map1->map_id, map2->map_id, i);
16914 return -EINVAL;
16915 }
16916 }
16917
16918 return 0;
16919}
16920
16921static int nl80211_nan_set_peer_sched(struct sk_buff *skb,
16922 struct genl_info *info)
16923{
16924 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16925 struct cfg80211_nan_channel *nan_channels __free(kfree) = NULL;
16926 struct cfg80211_nan_peer_sched sched = {};
16927 struct wireless_dev *wdev = info->user_ptr[1];
16928 struct nlattr *map_attr, *channel;
16929 int ret, n_maps = 0, n_channels = 0, i = 0, rem;
16930
16931 if (wdev->iftype != NL80211_IFTYPE_NAN)
16932 return -EOPNOTSUPP;
16933
16934 if (!info->attrs[NL80211_ATTR_MAC] ||
16935 !info->attrs[NL80211_ATTR_NAN_COMMITTED_DW]) {
16936 NL_SET_ERR_MSG(info->extack,
16937 "Required NAN peer schedule attributes are missing");
16938 return -EINVAL;
16939 }
16940
16941 /* First count how many channel attributes we got */
16942 nlmsg_for_each_attr_type(channel, NL80211_ATTR_NAN_CHANNEL,
16943 info->nlhdr, GENL_HDRLEN, rem)
16944 n_channels++;
16945
16946 if (!((info->attrs[NL80211_ATTR_NAN_SEQ_ID] &&
16947 info->attrs[NL80211_ATTR_NAN_PEER_MAPS] && n_channels) ||
16948 ((!info->attrs[NL80211_ATTR_NAN_SEQ_ID] &&
16949 !info->attrs[NL80211_ATTR_NAN_PEER_MAPS] && !n_channels)))) {
16950 NL_SET_ERR_MSG(info->extack,
16951 "Either provide all of: seq id, channels and maps, or none");
16952 return -EINVAL;
16953 }
16954
16955 /*
16956 * Limit the number of peer channels to:
16957 * local_channels * 4 (possible BWs) * 2 (possible NSS values)
16958 */
16959 if (n_channels && n_channels > wdev->u.nan.n_channels * 4 * 2) {
16960 NL_SET_ERR_MSG_FMT(info->extack,
16961 "Too many peer channels: %d (max %d)",
16962 n_channels,
16963 wdev->u.nan.n_channels * 4 * 2);
16964 return -EINVAL;
16965 }
16966
16967 if (n_channels) {
16968 nan_channels = kcalloc(n_channels, sizeof(*nan_channels),
16969 GFP_KERNEL);
16970 if (!nan_channels)
16971 return -ENOMEM;
16972 }
16973
16974 /* Parse peer channels */
16975 nlmsg_for_each_attr_type(channel, NL80211_ATTR_NAN_CHANNEL,
16976 info->nlhdr, GENL_HDRLEN, rem) {
16977 bool compatible = false;
16978
16979 ret = nl80211_parse_nan_channel(rdev, channel, info,
16980 nan_channels, i, false);
16981 if (ret)
16982 return ret;
16983
16984 /* Verify channel is compatible with at least one local channel */
16985 for (int j = 0; j < wdev->u.nan.n_channels; j++) {
16986 if (cfg80211_chandef_compatible(&nan_channels[i].chandef,
16987 &wdev->u.nan.chandefs[j])) {
16988 compatible = true;
16989 break;
16990 }
16991 }
16992 if (!compatible) {
16993 NL_SET_ERR_MSG_FMT(info->extack,
16994 "Channel %d not compatible with any local channel",
16995 i);
16996 return -EINVAL;
16997 }
16998 i++;
16999 }
17000
17001 sched.n_channels = n_channels;
17002 sched.nan_channels = nan_channels;
17003 sched.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
17004 sched.seq_id = nla_get_u8_default(info->attrs[NL80211_ATTR_NAN_SEQ_ID], 0);
17005 sched.committed_dw = nla_get_u16(info->attrs[NL80211_ATTR_NAN_COMMITTED_DW]);
17006 sched.max_chan_switch =
17007 nla_get_u16_default(info->attrs[NL80211_ATTR_NAN_MAX_CHAN_SWITCH_TIME], 0);
17008
17009 if (info->attrs[NL80211_ATTR_NAN_ULW]) {
17010 sched.ulw_size = nla_len(info->attrs[NL80211_ATTR_NAN_ULW]);
17011 sched.init_ulw = nla_data(info->attrs[NL80211_ATTR_NAN_ULW]);
17012 }
17013
17014 /* Initialize all maps as invalid */
17015 for (int j = 0; j < ARRAY_SIZE(sched.maps); j++)
17016 sched.maps[j].map_id = CFG80211_NAN_INVALID_MAP_ID;
17017
17018 if (info->attrs[NL80211_ATTR_NAN_PEER_MAPS]) {
17019 /* Parse each map */
17020 nla_for_each_nested(map_attr, info->attrs[NL80211_ATTR_NAN_PEER_MAPS],
17021 rem) {
17022 if (n_maps >= ARRAY_SIZE(sched.maps)) {
17023 NL_SET_ERR_MSG(info->extack, "Too many peer maps");
17024 return -EINVAL;
17025 }
17026
17027 ret = nl80211_parse_nan_peer_map(info, map_attr,
17028 &sched.maps[n_maps],
17029 n_channels);
17030 if (ret)
17031 return ret;
17032
17033 /* Validate against previous maps */
17034 for (int j = 0; j < n_maps; j++) {
17035 ret = nl80211_nan_validate_map_pair(&rdev->wiphy, info,
17036 &sched.maps[j],
17037 &sched.maps[n_maps],
17038 nan_channels);
17039 if (ret)
17040 return ret;
17041 }
17042
17043 n_maps++;
17044 }
17045 }
17046
17047 /* Verify each channel is scheduled at least once */
17048 for (int ch = 0; ch < n_channels; ch++) {
17049 bool scheduled = false;
17050
17051 for (int m = 0; m < n_maps && !scheduled; m++) {
17052 for (int s = 0; s < ARRAY_SIZE(sched.maps[m].schedule); s++) {
17053 if (sched.maps[m].schedule[s] == ch) {
17054 scheduled = true;
17055 break;
17056 }
17057 }
17058 }
17059 if (!scheduled) {
17060 NL_SET_ERR_MSG_FMT(info->extack,
17061 "Channel %d is not scheduled in any map",
17062 ch);
17063 return -EINVAL;
17064 }
17065 }
17066
17067 return rdev_nan_set_peer_sched(rdev, wdev, &sched);
17068}
17069
17070static bool nl80211_nan_is_sched_empty(struct cfg80211_nan_local_sched *sched)
17071{
17072 if (!sched->n_channels)
17073 return true;
17074
17075 for (int i = 0; i < ARRAY_SIZE(sched->schedule); i++) {
17076 if (sched->schedule[i] != NL80211_NAN_SCHED_NOT_AVAIL_SLOT)
17077 return false;
17078 }
17079
17080 return true;
17081}
17082
17083static int nl80211_nan_set_local_sched(struct sk_buff *skb,
17084 struct genl_info *info)
17085{
17086 struct cfg80211_registered_device *rdev = info->user_ptr[0];
17087 struct cfg80211_nan_local_sched *sched __free(kfree) = NULL;
17088 struct wireless_dev *wdev = info->user_ptr[1];
17089 int rem, i = 0, n_channels = 0, ret;
17090 struct nlattr *channel;
17091 bool sched_empty;
17092
17093 if (wdev->iftype != NL80211_IFTYPE_NAN)
17094 return -EOPNOTSUPP;
17095
17096 if (!wdev_running(wdev))
17097 return -ENOTCONN;
17098
17099 if (!info->attrs[NL80211_ATTR_NAN_TIME_SLOTS])
17100 return -EINVAL;
17101
17102 /* First count how many channel attributes we got */
17103 nlmsg_for_each_attr_type(channel, NL80211_ATTR_NAN_CHANNEL,
17104 info->nlhdr, GENL_HDRLEN, rem)
17105 n_channels++;
17106
17107 sched = kzalloc(struct_size(sched, nan_channels, n_channels),
17108 GFP_KERNEL);
17109 if (!sched)
17110 return -ENOMEM;
17111
17112 sched->n_channels = n_channels;
17113
17114 nlmsg_for_each_attr_type(channel, NL80211_ATTR_NAN_CHANNEL,
17115 info->nlhdr, GENL_HDRLEN, rem) {
17116 ret = nl80211_parse_nan_channel(rdev, channel, info,
17117 sched->nan_channels, i, true);
17118
17119 if (ret)
17120 return ret;
17121 i++;
17122 }
17123
17124 /* Parse and validate schedule */
17125 ret = nl80211_parse_nan_schedule(info,
17126 info->attrs[NL80211_ATTR_NAN_TIME_SLOTS],
17127 sched->schedule, sched->n_channels);
17128 if (ret)
17129 return ret;
17130
17131 sched_empty = nl80211_nan_is_sched_empty(sched);
17132
17133 sched->deferred =
17134 nla_get_flag(info->attrs[NL80211_ATTR_NAN_SCHED_DEFERRED]);
17135
17136 if (sched_empty) {
17137 if (sched->deferred) {
17138 NL_SET_ERR_MSG(info->extack,
17139 "Schedule cannot be deferred if all time slots are unavailable");
17140 return -EINVAL;
17141 }
17142
17143 if (info->attrs[NL80211_ATTR_NAN_AVAIL_BLOB]) {
17144 NL_SET_ERR_MSG(info->extack,
17145 "NAN Availability blob must be empty if all time slots are unavailable");
17146 return -EINVAL;
17147 }
17148 } else {
17149 if (!info->attrs[NL80211_ATTR_NAN_AVAIL_BLOB]) {
17150 NL_SET_ERR_MSG(info->extack,
17151 "NAN Availability blob attribute is required");
17152 return -EINVAL;
17153 }
17154
17155 sched->nan_avail_blob =
17156 nla_data(info->attrs[NL80211_ATTR_NAN_AVAIL_BLOB]);
17157 sched->nan_avail_blob_len =
17158 nla_len(info->attrs[NL80211_ATTR_NAN_AVAIL_BLOB]);
17159 }
17160
17161 return cfg80211_nan_set_local_schedule(rdev, wdev, sched);
17162}
17163
16424static int nl80211_get_protocol_features(struct sk_buff *skb,17164static int nl80211_get_protocol_features(struct sk_buff *skb,
16425 struct genl_info *info)17165 struct genl_info *info)
16426{17166{
@@ -18096,7 +18836,11 @@ nl80211_epcs_cfg(struct sk_buff *skb, struct genl_info *info) · 1669 unmodified lines
18096 NL80211_FLAG_NEED_RTNL) \18836 NL80211_FLAG_NEED_RTNL) \
18097 SELECTOR(__sel, WIPHY_CLEAR, \18837 SELECTOR(__sel, WIPHY_CLEAR, \
18098 NL80211_FLAG_NEED_WIPHY | \18838 NL80211_FLAG_NEED_WIPHY | \
18099 NL80211_FLAG_CLEAR_SKB)18839 NL80211_FLAG_CLEAR_SKB) \
18840 SELECTOR(__sel, WDEV_UP_RTNL_NOMTX, \
18841 NL80211_FLAG_NEED_WDEV_UP | \
18842 NL80211_FLAG_NO_WIPHY_MTX | \
18843 NL80211_FLAG_NEED_RTNL)
18100 18844
18101enum nl80211_internal_flags_selector {18845enum nl80211_internal_flags_selector {
18102#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,18846#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,
@@ -18933,6 +19677,7 @@ static const struct genl_small_ops nl80211_small_ops[] = { · 830 unmodified lines
18933 .doit = nl80211_stop_nan,19677 .doit = nl80211_stop_nan,
18934 .flags = GENL_ADMIN_PERM,19678 .flags = GENL_ADMIN_PERM,
18935 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |19679 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
19680 NL80211_FLAG_NO_WIPHY_MTX |
18936 NL80211_FLAG_NEED_RTNL),19681 NL80211_FLAG_NEED_RTNL),
18937 },19682 },
18938 {19683 {
@@ -19227,6 +19972,18 @@ static const struct genl_small_ops nl80211_small_ops[] = { · 288 unmodified lines
19227 .flags = GENL_UNS_ADMIN_PERM,19972 .flags = GENL_UNS_ADMIN_PERM,
19228 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),19973 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19229 },19974 },
19975 {
19976 .cmd = NL80211_CMD_NAN_SET_LOCAL_SCHED,
19977 .doit = nl80211_nan_set_local_sched,
19978 .flags = GENL_ADMIN_PERM,
19979 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19980 },
19981 {
19982 .cmd = NL80211_CMD_NAN_SET_PEER_SCHED,
19983 .doit = nl80211_nan_set_peer_sched,
19984 .flags = GENL_ADMIN_PERM,
19985 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19986 },
19230};19987};
19231 19988
19232static struct genl_family nl80211_fam __ro_after_init = {19989static struct genl_family nl80211_fam __ro_after_init = {
@@ -20527,7 +21284,7 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, · 1294 unmodified lines
20527 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);21284 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
20528 struct sk_buff *msg;21285 struct sk_buff *msg;
20529 void *hdr;21286 void *hdr;
20530 u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);21287 u32 nlportid = READ_ONCE(wdev->unexpected_nlportid);
20531 21288
20532 if (!nlportid)21289 if (!nlportid)
20533 return false;21290 return false;
@@ -20567,7 +21324,8 @@ bool cfg80211_rx_spurious_frame(struct net_device *dev, const u8 *addr, · 33 unmodified lines
20567 trace_cfg80211_rx_spurious_frame(dev, addr, link_id);21324 trace_cfg80211_rx_spurious_frame(dev, addr, link_id);
20568 21325
20569 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&21326 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
20570 wdev->iftype != NL80211_IFTYPE_P2P_GO)) {21327 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
21328 wdev->iftype != NL80211_IFTYPE_NAN_DATA)) {
20571 trace_cfg80211_return_bool(false);21329 trace_cfg80211_return_bool(false);
20572 return false;21330 return false;
20573 }21331 }
@@ -22137,6 +22895,97 @@ void cfg80211_nan_cluster_joined(struct wireless_dev *wdev, · 1563 unmodified lines
22137}22895}
22138EXPORT_SYMBOL(cfg80211_nan_cluster_joined);22896EXPORT_SYMBOL(cfg80211_nan_cluster_joined);
22139 22897
22898void cfg80211_nan_ulw_update(struct wireless_dev *wdev,
22899 const u8 *ulw, size_t ulw_len, gfp_t gfp)
22900{
22901 struct wiphy *wiphy = wdev->wiphy;
22902 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
22903 struct sk_buff *msg;
22904 void *hdr;
22905
22906 trace_cfg80211_nan_ulw_update(wiphy, wdev, ulw, ulw_len);
22907
22908 if (!wdev->owner_nlportid)
22909 return;
22910
22911 /* 32 for the wiphy idx, 64 for the wdev id, 100 for padding */
22912 msg = nlmsg_new(nla_total_size(sizeof(u32)) +
22913 nla_total_size(ulw_len) +
22914 nla_total_size(sizeof(u64)) + 100,
22915 gfp);
22916 if (!msg)
22917 return;
22918
22919 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_ULW_UPDATE);
22920 if (!hdr)
22921 goto nla_put_failure;
22922
22923 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
22924 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
22925 NL80211_ATTR_PAD) ||
22926 (ulw && ulw_len &&
22927 nla_put(msg, NL80211_ATTR_NAN_ULW, ulw_len, ulw)))
22928 goto nla_put_failure;
22929
22930 genlmsg_end(msg, hdr);
22931
22932 genlmsg_unicast(wiphy_net(wiphy), msg, wdev->owner_nlportid);
22933
22934 return;
22935
22936 nla_put_failure:
22937 nlmsg_free(msg);
22938}
22939EXPORT_SYMBOL(cfg80211_nan_ulw_update);
22940
22941void cfg80211_nan_channel_evac(struct wireless_dev *wdev,
22942 const struct cfg80211_chan_def *chandef,
22943 gfp_t gfp)
22944{
22945 struct wiphy *wiphy = wdev->wiphy;
22946 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
22947 struct sk_buff *msg;
22948 struct nlattr *chan_attr;
22949 void *hdr;
22950
22951 trace_cfg80211_nan_channel_evac(wiphy, wdev, chandef);
22952
22953 if (!wdev->owner_nlportid)
22954 return;
22955
22956 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
22957 if (!msg)
22958 return;
22959
22960 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_CHANNEL_EVAC);
22961 if (!hdr)
22962 goto nla_put_failure;
22963
22964 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
22965 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
22966 NL80211_ATTR_PAD))
22967 goto nla_put_failure;
22968
22969 chan_attr = nla_nest_start(msg, NL80211_ATTR_NAN_CHANNEL);
22970 if (!chan_attr)
22971 goto nla_put_failure;
22972
22973 if (nl80211_send_chandef(msg, chandef))
22974 goto nla_put_failure;
22975
22976 nla_nest_end(msg, chan_attr);
22977
22978 genlmsg_end(msg, hdr);
22979
22980 genlmsg_unicast(wiphy_net(wiphy), msg, wdev->owner_nlportid);
22981
22982 return;
22983
22984 nla_put_failure:
22985 nlmsg_free(msg);
22986}
22987EXPORT_SYMBOL(cfg80211_nan_channel_evac);
22988
22140/* initialisation/exit functions */22989/* initialisation/exit functions */
22141 22990
22142int __init nl80211_init(void)22991int __init nl80211_init(void)
net/wireless/rdev-ops.h+32−0
@@ -1060,6 +1060,38 @@ rdev_nan_change_conf(struct cfg80211_registered_device *rdev, · 1059 unmodified lines
1060 return ret;1060 return ret;
1061}1061}
1062 1062
1063static inline int
1064rdev_nan_set_local_sched(struct cfg80211_registered_device *rdev,
1065 struct wireless_dev *wdev,
1066 struct cfg80211_nan_local_sched *sched)
1067{
1068 int ret;
1069
1070 trace_rdev_nan_set_local_sched(&rdev->wiphy, wdev, sched);
1071 if (rdev->ops->nan_set_local_sched)
1072 ret = rdev->ops->nan_set_local_sched(&rdev->wiphy, wdev, sched);
1073 else
1074 ret = -EOPNOTSUPP;
1075 trace_rdev_return_int(&rdev->wiphy, ret);
1076 return ret;
1077}
1078
1079static inline int
1080rdev_nan_set_peer_sched(struct cfg80211_registered_device *rdev,
1081 struct wireless_dev *wdev,
1082 struct cfg80211_nan_peer_sched *sched)
1083{
1084 int ret;
1085
1086 trace_rdev_nan_set_peer_sched(&rdev->wiphy, wdev, sched);
1087 if (rdev->ops->nan_set_peer_sched)
1088 ret = rdev->ops->nan_set_peer_sched(&rdev->wiphy, wdev, sched);
1089 else
1090 ret = -EOPNOTSUPP;
1091 trace_rdev_return_int(&rdev->wiphy, ret);
1092 return ret;
1093}
1094
1063static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,1095static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
1064 struct net_device *dev,1096 struct net_device *dev,
1065 struct cfg80211_acl_data *params)1097 struct cfg80211_acl_data *params)
net/wireless/reg.c+21−6
@@ -2348,6 +2348,18 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) · 2347 unmodified lines
2348 if (!wdev->netdev || !netif_running(wdev->netdev))2348 if (!wdev->netdev || !netif_running(wdev->netdev))
2349 return true;2349 return true;
2350 2350
2351 /* NAN doesn't have links, handle it separately */
2352 if (iftype == NL80211_IFTYPE_NAN) {
2353 for (int i = 0; i < wdev->u.nan.n_channels; i++) {
2354 ret = cfg80211_reg_can_beacon(wiphy,
2355 &wdev->u.nan.chandefs[i],
2356 NL80211_IFTYPE_NAN);
2357 if (!ret)
2358 return false;
2359 }
2360 return true;
2361 }
2362
2351 for (link = 0; link < ARRAY_SIZE(wdev->links); link++) {2363 for (link = 0; link < ARRAY_SIZE(wdev->links); link++) {
2352 struct ieee80211_channel *chan;2364 struct ieee80211_channel *chan;
2353 2365
@@ -2397,9 +2409,9 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) · 43 unmodified lines
2397 continue;2409 continue;
2398 chandef = wdev->u.ocb.chandef;2410 chandef = wdev->u.ocb.chandef;
2399 break;2411 break;
2400 case NL80211_IFTYPE_NAN:2412 case NL80211_IFTYPE_NAN_DATA:
2401 /* we have no info, but NAN is also pretty universal */2413 /* NAN channels are checked in NL80211_IFTYPE_NAN interface */
2402 continue;2414 break;
2403 default:2415 default:
2404 /* others not implemented for now */2416 /* others not implemented for now */
2405 WARN_ON_ONCE(1);2417 WARN_ON_ONCE(1);
@@ -2436,11 +2448,14 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy) · 30 unmodified lines
2436 struct wireless_dev *wdev;2448 struct wireless_dev *wdev;
2437 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);2449 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
2438 2450
2439 guard(wiphy)(wiphy);2451 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
2452 bool valid;
2440 2453
2441 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)2454 scoped_guard(wiphy, wiphy)
2442 if (!reg_wdev_chan_valid(wiphy, wdev))2455 valid = reg_wdev_chan_valid(wiphy, wdev);
2456 if (!valid)
2443 cfg80211_leave(rdev, wdev, -1);2457 cfg80211_leave(rdev, wdev, -1);
2458 }
2444}2459}
2445 2460
2446static void reg_check_chans_work(struct work_struct *work)2461static void reg_check_chans_work(struct work_struct *work)
net/wireless/sysfs.c+14−13
@@ -102,25 +102,26 @@ static int wiphy_suspend(struct device *dev) · 101 unmodified lines
102 if (!rdev->wiphy.registered)102 if (!rdev->wiphy.registered)
103 goto out_unlock_rtnl;103 goto out_unlock_rtnl;
104 104
105 wiphy_lock(&rdev->wiphy);
106 if (rdev->wiphy.wowlan_config) {105 if (rdev->wiphy.wowlan_config) {
107 cfg80211_process_wiphy_works(rdev, NULL);106 scoped_guard(wiphy, &rdev->wiphy) {
108 if (rdev->ops->suspend)107 cfg80211_process_wiphy_works(rdev, NULL);
109 ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);108 if (rdev->ops->suspend)
110 if (ret <= 0)109 ret = rdev_suspend(rdev,
111 goto out_unlock_wiphy;110 rdev->wiphy.wowlan_config);
111 if (ret <= 0)
112 goto out_unlock_rtnl;
113 }
112 }114 }
113 115
114 /* Driver refused to configure wowlan (ret = 1) or no wowlan */116 /* Driver refused to configure wowlan (ret = 1) or no wowlan */
115 117
116 cfg80211_leave_all(rdev);118 cfg80211_leave_all(rdev);
117 cfg80211_process_rdev_events(rdev);119 scoped_guard(wiphy, &rdev->wiphy) {
118 cfg80211_process_wiphy_works(rdev, NULL);120 cfg80211_process_rdev_events(rdev);
119 if (rdev->ops->suspend)121 cfg80211_process_wiphy_works(rdev, NULL);
120 ret = rdev_suspend(rdev, NULL);122 if (rdev->ops->suspend)
121 123 ret = rdev_suspend(rdev, NULL);
122out_unlock_wiphy:124 }
123 wiphy_unlock(&rdev->wiphy);
124out_unlock_rtnl:125out_unlock_rtnl:
125 if (ret == 0)126 if (ret == 0)
126 rdev->suspended = true;127 rdev->suspended = true;
net/wireless/trace.h+105−0
@@ -2410,6 +2410,55 @@ TRACE_EVENT(rdev_del_nan_func, · 2409 unmodified lines
2410 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)2410 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
2411);2411);
2412 2412
2413TRACE_EVENT(rdev_nan_set_local_sched,
2414 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
2415 struct cfg80211_nan_local_sched *sched),
2416 TP_ARGS(wiphy, wdev, sched),
2417 TP_STRUCT__entry(
2418 WIPHY_ENTRY
2419 WDEV_ENTRY
2420 __array(u8, schedule, CFG80211_NAN_SCHED_NUM_TIME_SLOTS)
2421 ),
2422 TP_fast_assign(
2423 WIPHY_ASSIGN;
2424 WDEV_ASSIGN;
2425 memcpy(__entry->schedule, sched->schedule,
2426 CFG80211_NAN_SCHED_NUM_TIME_SLOTS);
2427 ),
2428 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", schedule: %s",
2429 WIPHY_PR_ARG, WDEV_PR_ARG,
2430 __print_array(__entry->schedule,
2431 CFG80211_NAN_SCHED_NUM_TIME_SLOTS, 1))
2432);
2433
2434TRACE_EVENT(rdev_nan_set_peer_sched,
2435 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
2436 struct cfg80211_nan_peer_sched *sched),
2437 TP_ARGS(wiphy, wdev, sched),
2438 TP_STRUCT__entry(
2439 WIPHY_ENTRY
2440 WDEV_ENTRY
2441 __array(u8, peer_addr, ETH_ALEN)
2442 __field(u8, seq_id)
2443 __field(u16, committed_dw)
2444 __field(u16, max_chan_switch)
2445 ),
2446 TP_fast_assign(
2447 WIPHY_ASSIGN;
2448 WDEV_ASSIGN;
2449 memcpy(__entry->peer_addr, sched->peer_addr, ETH_ALEN);
2450 __entry->seq_id = sched->seq_id;
2451 __entry->committed_dw = sched->committed_dw;
2452 __entry->max_chan_switch = sched->max_chan_switch;
2453 ),
2454 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT
2455 ", peer: %pM, seq_id: %u, committed_dw: 0x%x, max_chan_switch: %u",
2456 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->peer_addr,
2457 __entry->seq_id, __entry->committed_dw,
2458 __entry->max_chan_switch
2459 )
2460);
2461
2413TRACE_EVENT(rdev_set_mac_acl,2462TRACE_EVENT(rdev_set_mac_acl,
2414 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,2463 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
2415 struct cfg80211_acl_data *params),2464 struct cfg80211_acl_data *params),
@@ -4276,6 +4325,62 @@ TRACE_EVENT(cfg80211_incumbent_signal_notify, · 1860 unmodified lines
4276 TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", signal_interference_bitmap=0x%x",4325 TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", signal_interference_bitmap=0x%x",
4277 WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->signal_interference_bitmap)4326 WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->signal_interference_bitmap)
4278);4327);
4328
4329TRACE_EVENT(cfg80211_nan_sched_update_done,
4330 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, bool success),
4331 TP_ARGS(wiphy, wdev, success),
4332 TP_STRUCT__entry(
4333 WIPHY_ENTRY
4334 WDEV_ENTRY
4335 __field(bool, success)
4336 ),
4337 TP_fast_assign(
4338 WIPHY_ASSIGN;
4339 WDEV_ASSIGN;
4340 __entry->success = success;
4341 ),
4342 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT " success=%d",
4343 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->success)
4344);
4345
4346TRACE_EVENT(cfg80211_nan_ulw_update,
4347 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
4348 const u8 *ulw, size_t ulw_len),
4349 TP_ARGS(wiphy, wdev, ulw, ulw_len),
4350 TP_STRUCT__entry(
4351 WIPHY_ENTRY
4352 WDEV_ENTRY
4353 __dynamic_array(u8, ulw, ulw_len)
4354 ),
4355 TP_fast_assign(
4356 WIPHY_ASSIGN;
4357 WDEV_ASSIGN;
4358 if (ulw && ulw_len)
4359 memcpy(__get_dynamic_array(ulw), ulw, ulw_len);
4360 ),
4361 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT " ulw: %s",
4362 WIPHY_PR_ARG, WDEV_PR_ARG,
4363 __print_array(__get_dynamic_array(ulw),
4364 __get_dynamic_array_len(ulw), 1))
4365);
4366
4367TRACE_EVENT(cfg80211_nan_channel_evac,
4368 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
4369 const struct cfg80211_chan_def *chandef),
4370 TP_ARGS(wiphy, wdev, chandef),
4371 TP_STRUCT__entry(
4372 WDEV_ENTRY
4373 WIPHY_ENTRY
4374 CHAN_DEF_ENTRY
4375 ),
4376 TP_fast_assign(
4377 WDEV_ASSIGN;
4378 WIPHY_ASSIGN;
4379 CHAN_DEF_ASSIGN(chandef);
4380 ),
4381 TP_printk(WDEV_PR_FMT ", " WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
4382 WDEV_PR_ARG, WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
4383);
4279#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */4384#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
4280 4385
4281#undef TRACE_INCLUDE_PATH4386#undef TRACE_INCLUDE_PATH
net/wireless/util.c+22−6
@@ -90,7 +90,7 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band) · 89 unmodified lines
90 /* see 802.11ax D6.1 27.3.23.2 */90 /* see 802.11ax D6.1 27.3.23.2 */
91 if (chan == 2)91 if (chan == 2)
92 return MHZ_TO_KHZ(5935);92 return MHZ_TO_KHZ(5935);
93 if (chan <= 233)93 if (chan <= 253)
94 return MHZ_TO_KHZ(5950 + chan * 5);94 return MHZ_TO_KHZ(5950 + chan * 5);
95 break;95 break;
96 case NL80211_BAND_60GHZ:96 case NL80211_BAND_60GHZ:
@@ -625,8 +625,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, · 528 unmodified lines
625 case cpu_to_le16(0):625 case cpu_to_le16(0):
626 if (iftype != NL80211_IFTYPE_ADHOC &&626 if (iftype != NL80211_IFTYPE_ADHOC &&
627 iftype != NL80211_IFTYPE_STATION &&627 iftype != NL80211_IFTYPE_STATION &&
628 iftype != NL80211_IFTYPE_OCB)628 iftype != NL80211_IFTYPE_OCB &&
629 return -1;629 iftype != NL80211_IFTYPE_NAN_DATA)
630 return -1;
630 break;631 break;
631 }632 }
632 633
@@ -1144,8 +1145,15 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) · 511 unmodified lines
1144 ev->ij.channel);1145 ev->ij.channel);
1145 break;1146 break;
1146 case EVENT_STOPPED:1147 case EVENT_STOPPED:
1147 cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev,1148 /*
1148 ev->link_id);1149 * for NAN interfaces cfg80211_leave must be called but
1150 * locking here doesn't allow this.
1151 */
1152 if (WARN_ON(wdev->iftype == NL80211_IFTYPE_NAN))
1153 break;
1154
1155 cfg80211_leave_locked(wiphy_to_rdev(wdev->wiphy), wdev,
1156 ev->link_id);
1149 break;1157 break;
1150 case EVENT_PORT_AUTHORIZED:1158 case EVENT_PORT_AUTHORIZED:
1151 __cfg80211_port_authorized(wdev, ev->pa.peer_addr,1159 __cfg80211_port_authorized(wdev, ev->pa.peer_addr,
@@ -1184,6 +1192,13 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 32 unmodified lines
1184 if (otype == NL80211_IFTYPE_AP_VLAN)1192 if (otype == NL80211_IFTYPE_AP_VLAN)
1185 return -EOPNOTSUPP;1193 return -EOPNOTSUPP;
1186 1194
1195 /*
1196 * for NAN interfaces cfg80211_leave must be called for leaving,
1197 * but locking here doesn't allow this.
1198 */
1199 if (otype == NL80211_IFTYPE_NAN)
1200 return -EOPNOTSUPP;
1201
1187 /* cannot change into P2P device or NAN */1202 /* cannot change into P2P device or NAN */
1188 if (ntype == NL80211_IFTYPE_P2P_DEVICE ||1203 if (ntype == NL80211_IFTYPE_P2P_DEVICE ||
1189 ntype == NL80211_IFTYPE_NAN)1204 ntype == NL80211_IFTYPE_NAN)
@@ -1204,7 +1219,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 14 unmodified lines
1204 dev->ieee80211_ptr->use_4addr = false;1219 dev->ieee80211_ptr->use_4addr = false;
1205 rdev_set_qos_map(rdev, dev, NULL);1220 rdev_set_qos_map(rdev, dev, NULL);
1206 1221
1207 cfg80211_leave(rdev, dev->ieee80211_ptr, -1);1222 cfg80211_leave_locked(rdev, dev->ieee80211_ptr, -1);
1208 1223
1209 cfg80211_process_rdev_events(rdev);1224 cfg80211_process_rdev_events(rdev);
1210 cfg80211_mlme_purge_registrations(dev->ieee80211_ptr);1225 cfg80211_mlme_purge_registrations(dev->ieee80211_ptr);
@@ -1232,6 +1247,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 21 unmodified lines
1232 case NL80211_IFTYPE_OCB:1247 case NL80211_IFTYPE_OCB:
1233 case NL80211_IFTYPE_P2P_CLIENT:1248 case NL80211_IFTYPE_P2P_CLIENT:
1234 case NL80211_IFTYPE_ADHOC:1249 case NL80211_IFTYPE_ADHOC:
1250 case NL80211_IFTYPE_NAN_DATA:
1235 dev->priv_flags |= IFF_DONT_BRIDGE;1251 dev->priv_flags |= IFF_DONT_BRIDGE;
1236 break;1252 break;
1237 case NL80211_IFTYPE_P2P_GO:1253 case NL80211_IFTYPE_P2P_GO:

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t