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
10161016
10171017 netif_napi_add(ar->napi_dev, &ar->napi, ath10k_usb_napi_poll);
10181018
1019− usb_get_dev(dev);
10201019 vendor_id = le16_to_cpu(dev->descriptor.idVendor);
10211020 product_id = le16_to_cpu(dev->descriptor.idProduct);
10221021
@@ -1055,12 +1054,10 @@ err_usb_destroy: · 32 unmodified lines
10551054 err:
10561055 ath10k_core_destroy(ar);
10571056
1058− usb_put_dev(dev);
1059−
10601057 return ret;
10611058 }
10621059
1063−static void ath10k_usb_remove(struct usb_interface *interface)
1060+static void ath10k_usb_disconnect(struct usb_interface *interface)
10641061 {
10651062 struct ath10k_usb *ar_usb;
10661063
@@ -1071,7 +1068,6 @@ static void ath10k_usb_remove(struct usb_interface *interface) · 4 unmodified lines
10711068 ath10k_core_unregister(ar_usb->ar);
10721069 netif_napi_del(&ar_usb->ar->napi);
10731070 ath10k_usb_destroy(ar_usb->ar);
1074− usb_put_dev(interface_to_usbdev(interface));
10751071 ath10k_core_destroy(ar_usb->ar);
10761072 }
10771073
@@ -1117,7 +1113,7 @@ static struct usb_driver ath10k_usb_driver = { · 39 unmodified lines
11171113 .probe = ath10k_usb_probe,
11181114 .suspend = ath10k_usb_pm_suspend,
11191115 .resume = ath10k_usb_pm_resume,
1120− .disconnect = ath10k_usb_remove,
1116+ .disconnect = ath10k_usb_disconnect,
11211117 .id_table = ath10k_usb_ids,
11221118 .supports_autosuspend = true,
11231119 .disable_hub_initiated_lpm = 1,
drivers/net/wireless/ath/ath12k/ahb.h+2−2
@@ -21,8 +21,8 @@ · 20 unmodified lines
2121 #define ATH12K_ROOTPD_READY_TIMEOUT (5 * HZ)
2222 #define ATH12K_RPROC_AFTER_POWERUP QCOM_SSR_AFTER_POWERUP
2323 #define ATH12K_AHB_FW_PREFIX "q6_fw"
24−#define ATH12K_AHB_FW_SUFFIX ".mdt"
25−#define ATH12K_AHB_FW2 "iu_fw.mdt"
24+#define ATH12K_AHB_FW_SUFFIX ".mbn"
25+#define ATH12K_AHB_FW2 "iu_fw.mbn"
2626 #define ATH12K_AHB_UPD_SWID 0x12
2727 #define ATH12K_USERPD_SPAWN_TIMEOUT (5 * HZ)
2828 #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
523523 u16 links_map;
524524 u8 assoc_link_id;
525525 u16 ml_peer_id;
526− u8 num_peer;
526+ u16 free_logical_link_idx_map;
527527
528528 enum ieee80211_sta_state state;
529529 };
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
205205 if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE)))
206206 return;
207207
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))
209209 is_ampdu =
210210 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− }
218211
219212 if (usr_stats->tlv_flags &
220213 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
223216 HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M);
224217 tid = le32_get_bits(usr_stats->ack_ba.info,
225218 HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM);
226− }
227219
228− if (common->fes_duration_us)
229− tx_duration = le32_to_cpu(common->fes_duration_us);
220+ if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {
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+ }
230232
231233 user_rate = &usr_stats->rate;
232234 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
268268 };
269269
270270 enum hal_rx_legacy_rate {
271− HAL_RX_LEGACY_RATE_1_MBPS,
272− HAL_RX_LEGACY_RATE_2_MBPS,
273− HAL_RX_LEGACY_RATE_5_5_MBPS,
274− HAL_RX_LEGACY_RATE_6_MBPS,
275− HAL_RX_LEGACY_RATE_9_MBPS,
276− HAL_RX_LEGACY_RATE_11_MBPS,
277− HAL_RX_LEGACY_RATE_12_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,
271+ HAL_RX_LEGACY_RATE_LP_1_MBPS,
272+ HAL_RX_LEGACY_RATE_LP_2_MBPS,
273+ HAL_RX_LEGACY_RATE_LP_5_5_MBPS,
274+ HAL_RX_LEGACY_RATE_LP_11_MBPS,
275+ HAL_RX_LEGACY_RATE_SP_2_MBPS,
276+ HAL_RX_LEGACY_RATE_SP_5_5_MBPS,
277+ HAL_RX_LEGACY_RATE_SP_11_MBPS,
283278 HAL_RX_LEGACY_RATE_INVALID,
284279 };
285280
281+enum 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+
286293 enum hal_ring_type {
287294 HAL_REO_DST,
288295 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
164164 CHAN6G(233, 7115, 0),
165165 };
166166
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+
167175 static struct ieee80211_rate ath12k_legacy_rates[] = {
168176 { .bitrate = 10,
169177 .hw_value = ATH12K_HW_RATE_CCK_LP_1M },
170− { .bitrate = 20,
171− .hw_value = ATH12K_HW_RATE_CCK_LP_2M,
172− .hw_value_short = ATH12K_HW_RATE_CCK_SP_2M,
173− .flags = IEEE80211_RATE_SHORT_PREAMBLE },
174− { .bitrate = 55,
175− .hw_value = ATH12K_HW_RATE_CCK_LP_5_5M,
176− .hw_value_short = ATH12K_HW_RATE_CCK_SP_5_5M,
177− .flags = IEEE80211_RATE_SHORT_PREAMBLE },
178− { .bitrate = 110,
179− .hw_value = ATH12K_HW_RATE_CCK_LP_11M,
180− .hw_value_short = ATH12K_HW_RATE_CCK_SP_11M,
181− .flags = IEEE80211_RATE_SHORT_PREAMBLE },
182−
183− { .bitrate = 60, .hw_value = ATH12K_HW_RATE_OFDM_6M },
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 },
178+ ATH12K_MAC_RATE_B(20, ATH12K_HW_RATE_CCK_LP_2M,
179+ ATH12K_HW_RATE_CCK_SP_2M),
180+ ATH12K_MAC_RATE_B(55, ATH12K_HW_RATE_CCK_LP_5_5M,
181+ ATH12K_HW_RATE_CCK_SP_5_5M),
182+ ATH12K_MAC_RATE_B(110, ATH12K_HW_RATE_CCK_LP_11M,
183+ ATH12K_HW_RATE_CCK_SP_11M),
184+ ATH12K_MAC_RATE_A_M(60, ATH12K_HW_RATE_OFDM_6M),
185+ ATH12K_MAC_RATE_A_M(90, ATH12K_HW_RATE_OFDM_9M),
186+ ATH12K_MAC_RATE_A_M(120, ATH12K_HW_RATE_OFDM_12M),
187+ ATH12K_MAC_RATE_A_M(180, ATH12K_HW_RATE_OFDM_18M),
188+ ATH12K_MAC_RATE_A_M(240, ATH12K_HW_RATE_OFDM_24M),
189+ ATH12K_MAC_RATE_A_M(360, ATH12K_HW_RATE_OFDM_36M),
190+ ATH12K_MAC_RATE_A_M(480, ATH12K_HW_RATE_OFDM_48M),
191+ ATH12K_MAC_RATE_A_M(540, ATH12K_HW_RATE_OFDM_54M),
191192 };
192193
193194 static const int
@@ -732,11 +733,17 @@ u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband, · 538 unmodified lines
732733 if (ath12k_mac_bitrate_is_cck(rate->bitrate) != cck)
733734 continue;
734735
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))
736739 return i;
740+ /* To handle 802.11b short PPDU type */
737741 else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
738742 rate->hw_value_short == hw_rate)
739743 return i;
744+ /* To handle 802.11b long PPDU type */
745+ else if (rate->hw_value == hw_rate)
746+ return i;
740747 }
741748
742749 return 0;
@@ -6786,6 +6793,8 @@ static void ath12k_mac_free_unassign_link_sta(struct ath12k_hw *ah, · 6043 unmodified lines
67866793 return;
67876794
67886795 ahsta->links_map &= ~BIT(link_id);
6796+ ahsta->free_logical_link_idx_map |= BIT(arsta->link_idx);
6797+
67896798 rcu_assign_pointer(ahsta->link[link_id], NULL);
67906799 synchronize_rcu();
67916800
@@ -7104,6 +7113,7 @@ static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah, · 312 unmodified lines
71047113 struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
71057114 struct ieee80211_link_sta *link_sta;
71067115 struct ath12k_link_vif *arvif;
7116+ int link_idx;
71077117
71087118 lockdep_assert_wiphy(ah->hw->wiphy);
71097119
@@ -7122,8 +7132,16 @@ static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah, · 12 unmodified lines
71227132
71237133 ether_addr_copy(arsta->addr, link_sta->addr);
71247134
7125− /* logical index of the link sta in order of creation */
7126− arsta->link_idx = ahsta->num_peer++;
7135+ if (!ahsta->free_logical_link_idx_map)
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;
71277145
71287146 arsta->link_id = link_id;
71297147 ahsta->links_map |= BIT(arsta->link_id);
@@ -7632,6 +7650,7 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, · 502 unmodified lines
76327650 if (old_state == IEEE80211_STA_NOTEXIST &&
76337651 new_state == IEEE80211_STA_NONE) {
76347652 memset(ahsta, 0, sizeof(*ahsta));
7653+ ahsta->free_logical_link_idx_map = U16_MAX;
76357654
76367655 arsta = &ahsta->deflink;
76377656
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
405405 }
406406 }
407407
408+static __always_inline u8
409+ath12k_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+
408444 static void
409445 ath12k_wifi7_dp_mon_parse_l_sig_b(const struct hal_rx_lsig_b_info *lsigb,
410446 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
415451 rate = u32_get_bits(info0, HAL_RX_LSIG_B_INFO_INFO0_RATE);
416452 switch (rate) {
417453 case 1:
418− rate = HAL_RX_LEGACY_RATE_1_MBPS;
454+ rate = HAL_RX_LEGACY_RATE_LP_1_MBPS;
419455 break;
420456 case 2:
421− case 5:
422− rate = HAL_RX_LEGACY_RATE_2_MBPS;
457+ rate = HAL_RX_LEGACY_RATE_LP_2_MBPS;
423458 break;
424459 case 3:
425− case 6:
426− rate = HAL_RX_LEGACY_RATE_5_5_MBPS;
460+ rate = HAL_RX_LEGACY_RATE_LP_5_5_MBPS;
427461 break;
428462 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;
429471 case 7:
430− rate = HAL_RX_LEGACY_RATE_11_MBPS;
472+ rate = HAL_RX_LEGACY_RATE_SP_11_MBPS;
431473 break;
432474 default:
433475 rate = HAL_RX_LEGACY_RATE_INVALID;
476+ break;
434477 }
435478
436− ppdu_info->rate = rate;
479+ ppdu_info->rate = ath12k_wifi7_hal_mon_map_legacy_rate_to_hw_rate(rate);
437480 ppdu_info->cck_flag = 1;
438481 }
439482
@@ -447,31 +490,32 @@ ath12k_wifi7_dp_mon_parse_l_sig_a(const struct hal_rx_lsig_a_info *lsiga, · 7 unmodified lines
447490 rate = u32_get_bits(info0, HAL_RX_LSIG_A_INFO_INFO0_RATE);
448491 switch (rate) {
449492 case 8:
450− rate = HAL_RX_LEGACY_RATE_48_MBPS;
493+ rate = HAL_RX_LEGACY_RATE_OFDM_48_MBPS;
451494 break;
452495 case 9:
453− rate = HAL_RX_LEGACY_RATE_24_MBPS;
496+ rate = HAL_RX_LEGACY_RATE_OFDM_24_MBPS;
454497 break;
455498 case 10:
456− rate = HAL_RX_LEGACY_RATE_12_MBPS;
499+ rate = HAL_RX_LEGACY_RATE_OFDM_12_MBPS;
457500 break;
458501 case 11:
459− rate = HAL_RX_LEGACY_RATE_6_MBPS;
502+ rate = HAL_RX_LEGACY_RATE_OFDM_6_MBPS;
460503 break;
461504 case 12:
462− rate = HAL_RX_LEGACY_RATE_54_MBPS;
505+ rate = HAL_RX_LEGACY_RATE_OFDM_54_MBPS;
463506 break;
464507 case 13:
465− rate = HAL_RX_LEGACY_RATE_36_MBPS;
508+ rate = HAL_RX_LEGACY_RATE_OFDM_36_MBPS;
466509 break;
467510 case 14:
468− rate = HAL_RX_LEGACY_RATE_18_MBPS;
511+ rate = HAL_RX_LEGACY_RATE_OFDM_18_MBPS;
469512 break;
470513 case 15:
471− rate = HAL_RX_LEGACY_RATE_9_MBPS;
514+ rate = HAL_RX_LEGACY_RATE_OFDM_9_MBPS;
472515 break;
473516 default:
474− rate = HAL_RX_LEGACY_RATE_INVALID;
517+ rate = HAL_RX_LEGACY_RATE_OFDM_INVALID;
518+ break;
475519 }
476520
477521 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
1001710017
1001810018 static int
1001910019 ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,
10020− struct wmi_unit_test_cmd ut_cmd,
10021− u32 *test_args)
10020+ const struct wmi_unit_test_arg *ut)
1002210021 {
1002310022 struct ath12k_wmi_pdev *wmi = ar->wmi;
1002410023 struct wmi_unit_test_cmd *cmd;
10024+ int buf_len, arg_len;
1002510025 struct sk_buff *skb;
1002610026 struct wmi_tlv *tlv;
10027+ __le32 *ut_cmd_args;
1002710028 void *ptr;
10028− u32 *ut_cmd_args;
10029− int buf_len, arg_len;
1003010029 int ret;
1003110030 int i;
1003210031
10033− arg_len = sizeof(u32) * le32_to_cpu(ut_cmd.num_args);
10034− buf_len = sizeof(ut_cmd) + arg_len + TLV_HDR_SIZE;
10032+ arg_len = sizeof(*ut_cmd_args) * ut->num_args;
10033+ buf_len = sizeof(*cmd) + arg_len + TLV_HDR_SIZE;
1003510034
1003610035 skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, buf_len);
1003710036 if (!skb)
1003810037 return -ENOMEM;
1003910038
10040− cmd = (struct wmi_unit_test_cmd *)skb->data;
10039+ ptr = skb->data;
10040+ cmd = ptr;
1004110041 cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_UNIT_TEST_CMD,
10042− sizeof(ut_cmd));
10043−
10044− cmd->vdev_id = ut_cmd.vdev_id;
10045− cmd->module_id = ut_cmd.module_id;
10046− cmd->num_args = ut_cmd.num_args;
10047− cmd->diag_token = ut_cmd.diag_token;
10048−
10049− ptr = skb->data + sizeof(ut_cmd);
10042+ sizeof(*cmd));
10043+ cmd->vdev_id = cpu_to_le32(ut->vdev_id);
10044+ cmd->module_id = cpu_to_le32(ut->module_id);
10045+ cmd->num_args = cpu_to_le32(ut->num_args);
10046+ cmd->diag_token = cpu_to_le32(ut->diag_token);
1005010047
10048+ ptr += sizeof(*cmd);
1005110049 tlv = ptr;
1005210050 tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, arg_len);
1005310051
1005410052 ptr += TLV_HDR_SIZE;
10055−
1005610053 ut_cmd_args = ptr;
10057− for (i = 0; i < le32_to_cpu(ut_cmd.num_args); i++)
10058− ut_cmd_args[i] = test_args[i];
10054+ for (i = 0; i < ut->num_args; i++)
10055+ ut_cmd_args[i] = cpu_to_le32(ut->args[i]);
1005910056
1006010057 ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
1006110058 "WMI unit test : module %d vdev %d n_args %d token %d\n",
10062− cmd->module_id, cmd->vdev_id, cmd->num_args,
10063− cmd->diag_token);
10059+ ut->module_id, ut->vdev_id, ut->num_args, ut->diag_token);
1006410060
1006510061 ret = ath12k_wmi_cmd_send(wmi, skb, WMI_UNIT_TEST_CMDID);
1006610062
@@ -10076,8 +10072,7 @@ ath12k_wmi_send_unit_test_cmd(struct ath12k *ar, · 9 unmodified lines
1007610072 int ath12k_wmi_simulate_radar(struct ath12k *ar)
1007710073 {
1007810074 struct ath12k_link_vif *arvif;
10079− u32 dfs_args[DFS_MAX_TEST_ARGS];
10080− struct wmi_unit_test_cmd wmi_ut;
10075+ struct wmi_unit_test_arg wmi_ut = {};
1008110076 bool arvif_found = false;
1008210077
1008310078 list_for_each_entry(arvif, &ar->arvifs, list) {
@@ -10090,22 +10085,23 @@ int ath12k_wmi_simulate_radar(struct ath12k *ar) · 6 unmodified lines
1009010085 if (!arvif_found)
1009110086 return -EINVAL;
1009210087
10093− dfs_args[DFS_TEST_CMDID] = 0;
10094− dfs_args[DFS_TEST_PDEV_ID] = ar->pdev->pdev_id;
10095− /* Currently we could pass segment_id(b0 - b1), chirp(b2)
10088+ wmi_ut.args[DFS_TEST_CMDID] = 0;
10089+ wmi_ut.args[DFS_TEST_PDEV_ID] = ar->pdev->pdev_id;
10090+ /*
10091+ * Currently we could pass segment_id(b0 - b1), chirp(b2)
1009610092 * freq offset (b3 - b10) to unit test. For simulation
1009710093 * purpose this can be set to 0 which is valid.
1009810094 */
10099− dfs_args[DFS_TEST_RADAR_PARAM] = 0;
10095+ wmi_ut.args[DFS_TEST_RADAR_PARAM] = 0;
1010010096
10101− wmi_ut.vdev_id = cpu_to_le32(arvif->vdev_id);
10102− wmi_ut.module_id = cpu_to_le32(DFS_UNIT_TEST_MODULE);
10103− wmi_ut.num_args = cpu_to_le32(DFS_MAX_TEST_ARGS);
10104− wmi_ut.diag_token = cpu_to_le32(DFS_UNIT_TEST_TOKEN);
10097+ wmi_ut.vdev_id = arvif->vdev_id;
10098+ wmi_ut.module_id = DFS_UNIT_TEST_MODULE;
10099+ wmi_ut.num_args = DFS_MAX_TEST_ARGS;
10100+ wmi_ut.diag_token = DFS_UNIT_TEST_TOKEN;
1010510101
1010610102 ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Triggering Radar Simulation\n");
1010710103
10108− return ath12k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args);
10104+ return ath12k_wmi_send_unit_test_cmd(ar, &wmi_ut);
1010910105 }
1011010106
1011110107 int 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
41934193 struct ath12k_wmi_mac_addr_params peer_macaddr;
41944194 } __packed;
41954195
4196−#define DFS_PHYERR_UNIT_TEST_CMD 0
41974196 #define DFS_UNIT_TEST_MODULE 0x2b
41984197 #define DFS_UNIT_TEST_TOKEN 0xAA
41994198
@@ -4204,10 +4203,15 @@ enum dfs_test_args_idx { · 4 unmodified lines
42044203 DFS_MAX_TEST_ARGS,
42054204 };
42064205
4207−struct wmi_dfs_unit_test_arg {
4208− u32 cmd_id;
4209− u32 pdev_id;
4210− u32 radar_param;
4206+/* update if another test command requires more */
4207+#define WMI_UNIT_TEST_ARGS_MAX DFS_MAX_TEST_ARGS
4208+
4209+struct 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];
42114215 };
42124216
42134217 struct 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
11241124 int vendor_id, product_id;
11251125 int ret = 0;
11261126
1127− usb_get_dev(dev);
1128−
11291127 vendor_id = le16_to_cpu(dev->descriptor.idVendor);
11301128 product_id = le16_to_cpu(dev->descriptor.idProduct);
11311129
@@ -1143,11 +1141,8 @@ static int ath6kl_usb_probe(struct usb_interface *interface, · 11 unmodified lines
11431141 ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n");
11441142
11451143 ar_usb = ath6kl_usb_create(interface);
1146−
1147− if (ar_usb == NULL) {
1148− ret = -ENOMEM;
1149− goto err_usb_put;
1150− }
1144+ if (ar_usb == NULL)
1145+ return -ENOMEM;
11511146
11521147 ar = ath6kl_core_create(&ar_usb->udev->dev);
11531148 if (ar == NULL) {
@@ -1176,15 +1171,12 @@ err_core_free: · 22 unmodified lines
11761171 ath6kl_core_destroy(ar);
11771172 err_usb_destroy:
11781173 ath6kl_usb_destroy(ar_usb);
1179−err_usb_put:
1180− usb_put_dev(dev);
11811174
11821175 return ret;
11831176 }
11841177
1185−static void ath6kl_usb_remove(struct usb_interface *interface)
1178+static void ath6kl_usb_disconnect(struct usb_interface *interface)
11861179 {
1187− usb_put_dev(interface_to_usbdev(interface));
11881180 ath6kl_usb_device_detached(interface);
11891181 }
11901182
@@ -1235,7 +1227,7 @@ static struct usb_driver ath6kl_usb_driver = { · 44 unmodified lines
12351227 .probe = ath6kl_usb_probe,
12361228 .suspend = ath6kl_usb_pm_suspend,
12371229 .resume = ath6kl_usb_pm_resume,
1238− .disconnect = ath6kl_usb_remove,
1230+ .disconnect = ath6kl_usb_disconnect,
12391231 .id_table = ath6kl_usb_ids,
12401232 .supports_autosuspend = true,
12411233 .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
16301630 WMI_LOCK_BSS_MODE = 3, /* Lock to the current BSS */
16311631 };
16321632
1633−struct bss_bias {
1634− u8 bssid[ETH_ALEN];
1635− s8 bias;
1636−} __packed;
1637−
1638−struct bss_bias_info {
1639− u8 num_bss;
1640− struct bss_bias bss_bias[];
1641−} __packed;
1642−
16431633 struct low_rssi_scan_params {
16441634 __le16 lrssi_scan_period;
16451635 a_sle16 lrssi_scan_threshold;
@@ -1652,7 +1642,6 @@ struct roam_ctrl_cmd { · 6 unmodified lines
16521642 union {
16531643 u8 bssid[ETH_ALEN]; /* WMI_FORCE_ROAM */
16541644 u8 roam_mode; /* WMI_SET_ROAM_MODE */
1655− struct bss_bias_info bss; /* WMI_SET_HOST_BIAS */
16561645 struct low_rssi_scan_params params; /* WMI_SET_LRSSI_SCAN_PARAMS
16571646 */
16581647 } __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
13821382 goto err_alloc;
13831383 }
13841384
1385− usb_get_dev(udev);
1386−
13871385 hif_dev->udev = udev;
13881386 hif_dev->interface = interface;
13891387 hif_dev->usb_device_id = id;
@@ -1403,7 +1401,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, · 13 unmodified lines
14031401 err_fw_req:
14041402 usb_set_intfdata(interface, NULL);
14051403 kfree(hif_dev);
1406− usb_put_dev(udev);
14071404 err_alloc:
14081405 return ret;
14091406 }
@@ -1451,7 +1448,6 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) · 41 unmodified lines
14511448
14521449 kfree(hif_dev);
14531450 dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");
1454− usb_put_dev(udev);
14551451 }
14561452
14571453 #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
837837 struct b43_dmaring *ring;
838838 int i, err;
839839 dma_addr_t dma_test;
840+ size_t nr_slots;
840841
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);
842848 if (!ring)
843849 goto out;
844850
845− ring->nr_slots = B43_RXRING_SLOTS;
846− if (for_tx)
847− ring->nr_slots = B43_TXRING_SLOTS;
851+ ring->nr_slots = nr_slots;
848852
849− ring->meta = kzalloc_objs(struct b43_dmadesc_meta, ring->nr_slots);
850− if (!ring->meta)
851− goto err_kfree_ring;
852853 for (i = 0; i < ring->nr_slots; i++)
853854 ring->meta->skb = B43_DMA_PTR_POISON;
854855
@@ -943,8 +944,6 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, · 88 unmodified lines
943944 err_kfree_txhdr_cache:
944945 kfree(ring->txhdr_cache);
945946 err_kfree_meta:
946− kfree(ring->meta);
947− err_kfree_ring:
948947 kfree(ring);
949948 ring = NULL;
950949 goto out;
@@ -1004,7 +1003,6 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring, · 53 unmodified lines
10041003 free_ringmemory(ring);
10051004
10061005 kfree(ring->txhdr_cache);
1007− kfree(ring->meta);
10081006 kfree(ring);
10091007 }
10101008
drivers/net/wireless/broadcom/b43/dma.h+2−2
@@ -228,8 +228,6 @@ struct b43_dmaring { · 227 unmodified lines
228228 const struct b43_dma_ops *ops;
229229 /* Kernel virtual base address of the ring memory. */
230230 void *descbase;
231− /* Meta data about all descriptors. */
232− struct b43_dmadesc_meta *meta;
233231 /* Cache of TX headers for each TX frame.
234232 * This is to avoid an allocation on each TX.
235233 * This is NULL for an RX ring.
@@ -273,6 +271,8 @@ struct b43_dmaring { · 37 unmodified lines
273271 /* Statistics: Total number of TX plus all retries. */
274272 u64 nr_total_packet_tries;
275273 #endif /* CONFIG_B43_DEBUG */
274+ /* Meta data about all descriptors. */
275+ struct b43_dmadesc_meta meta[] __counted_by(nr_slots);
276276 };
277277
278278 static 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
1010 #include "fw/api/txq.h"
1111
1212 /* Highest firmware core release supported */
13−#define IWL_BZ_UCODE_CORE_MAX 101
13+#define IWL_BZ_UCODE_CORE_MAX 102
1414
1515 /* Lowest firmware API version supported */
1616 #define IWL_BZ_UCODE_API_MIN 100
drivers/net/wireless/intel/iwlwifi/cfg/dr.c+1−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
99 #include "fw/api/txq.h"
1010
1111 /* Highest firmware core release supported */
12−#define IWL_DR_UCODE_CORE_MAX 101
12+#define IWL_DR_UCODE_CORE_MAX 102
1313
1414 /* Lowest firmware API version supported */
1515 #define IWL_DR_UCODE_API_MIN 100
drivers/net/wireless/intel/iwlwifi/cfg/sc.c+1−1
@@ -10,7 +10,7 @@ · 9 unmodified lines
1010 #include "fw/api/txq.h"
1111
1212 /* Highest firmware core release supported */
13−#define IWL_SC_UCODE_CORE_MAX 101
13+#define IWL_SC_UCODE_CORE_MAX 102
1414
1515 /* Lowest firmware API version supported */
1616 #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
504504 u8 num_chains, u8 num_sub_bands)
505505 {
506506 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);
508509 subband++) {
509510 /* if we don't have the values, use the default */
510511 if (subband >= num_sub_bands) {
@@ -534,7 +535,23 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt) · 23 unmodified lines
534535 if (IS_ERR(data))
535536 return PTR_ERR(data);
536537
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 */
538555 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
539556 ACPI_WRDS_WIFI_DATA_SIZE_REV2,
540557 &tbl_rev);
@@ -591,6 +608,13 @@ read_table: · 50 unmodified lines
591608 goto out_free;
592609 }
593610
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+
594618 IWL_DEBUG_RADIO(fwrt, "Reading WRDS tbl_rev=%d\n", tbl_rev);
595619
596620 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
624648 if (IS_ERR(data))
625649 return PTR_ERR(data);
626650
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 */
628667 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
629668 ACPI_EWRD_WIFI_DATA_SIZE_REV2,
630669 &tbl_rev);
@@ -679,6 +718,13 @@ read_table: · 48 unmodified lines
679718 goto out_free;
680719 }
681720
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+
682728 enabled = !!(wifi_pkg->package.elements[1].integer.value);
683729 n_profiles = wifi_pkg->package.elements[2].integer.value;
684730
@@ -721,6 +767,13 @@ read_table: · 36 unmodified lines
721767 if (tbl_rev < 2)
722768 goto set_enabled;
723769
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+
724777 /* parse cdb chains for all profiles */
725778 for (i = 0; i < n_profiles; i++) {
726779 struct iwl_sar_profile_chain *chains;
@@ -759,6 +812,12 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt) · 32 unmodified lines
759812 u8 profiles;
760813 u8 min_profiles;
761814 } 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+ },
762821 {
763822 .revisions = BIT(3),
764823 .bands = ACPI_GEO_NUM_BANDS_REV2,
@@ -812,6 +871,18 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt) · 47 unmodified lines
812871 num_bands = rev_data[idx].bands;
813872 num_profiles = rev_data[idx].profiles;
814873
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+
815886 if (rev_data[idx].min_profiles) {
816887 /* read header that says # of profiles */
817888 union acpi_object *entry;
@@ -851,18 +922,20 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt) · 33 unmodified lines
851922
852923 read_table:
853924 fwrt->geo_rev = tbl_rev;
925+
854926 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++) {
856930 union acpi_object *entry;
857931
858932 /*
859− * num_bands is either 2 or 3, if it's only 2 then
860− * fill the third band (6 GHz) with the values from
861− * 5 GHz (second band)
933+ * num_bands is either 2 or 3 or 4, if it's lower
934+ * than 4, fill the third band (6 GHz) with the values
935+ * from 5 GHz (second band)
862936 */
863937 if (j >= num_bands) {
864− fwrt->geo_profiles[i].bands[j].max =
865− fwrt->geo_profiles[i].bands[1].max;
938+ prof->bands[j].max = prof->bands[1].max;
866939 } else {
867940 entry = &wifi_pkg->package.elements[entry_idx];
868941 entry_idx++;
@@ -872,15 +945,17 @@ read_table: · 3 unmodified lines
872945 goto out_free;
873946 }
874947
875− fwrt->geo_profiles[i].bands[j].max =
948+ prof->bands[j].max =
876949 entry->integer.value;
877950 }
878951
879− for (k = 0; k < BIOS_GEO_NUM_CHAINS; k++) {
952+ for (k = 0;
953+ k < ARRAY_SIZE(prof->bands[0].chains);
954+ k++) {
880955 /* same here as above */
881956 if (j >= num_bands) {
882− fwrt->geo_profiles[i].bands[j].chains[k] =
883− fwrt->geo_profiles[i].bands[1].chains[k];
957+ prof->bands[j].chains[k] =
958+ prof->bands[1].chains[k];
884959 } else {
885960 entry = &wifi_pkg->package.elements[entry_idx];
886961 entry_idx++;
@@ -890,7 +965,7 @@ read_table: · 3 unmodified lines
890965 goto out_free;
891966 }
892967
893− fwrt->geo_profiles[i].bands[j].chains[k] =
968+ prof->bands[j].chains[k] =
894969 entry->integer.value;
895970 }
896971 }
@@ -898,6 +973,7 @@ read_table: · 1 unmodified line
898973 }
899974
900975 fwrt->geo_num_profiles = num_profiles;
976+ fwrt->geo_bios_source = BIOS_SOURCE_ACPI;
901977 fwrt->geo_enabled = true;
902978 ret = 0;
903979 out_free:
@@ -915,6 +991,22 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt) · 11 unmodified lines
915991 if (IS_ERR(data))
916992 return PTR_ERR(data);
917993
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+
9181010 /* try to read ppag table rev 1 to 4 (all have the same data size) */
9191011 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
9201012 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
9501042 goto out_free;
9511043
9521044 read_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+
9531054 fwrt->ppag_bios_rev = tbl_rev;
9541055 flags = &wifi_pkg->package.elements[1];
9551056
@@ -966,7 +1067,7 @@ read_table: · 10 unmodified lines
9661067 * first sub-band (j=0) corresponds to Low-Band (2.4GHz), and the
9671068 * following sub-bands to High-Band (5GHz).
9681069 */
969− for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
1070+ for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
9701071 for (j = 0; j < num_sub_bands; j++) {
9711072 union acpi_object *ent;
9721073
@@ -980,6 +1081,7 @@ read_table: · 7 unmodified lines
9801081 }
9811082 }
9821083
1084+ iwl_bios_print_ppag(fwrt, num_sub_bands);
9831085 fwrt->ppag_bios_source = BIOS_SOURCE_ACPI;
9841086 ret = 0;
9851087
drivers/net/wireless/intel/iwlwifi/fw/acpi.h+19−9
@@ -8,11 +8,6 @@ · 7 unmodified lines
88
99 #include <linux/acpi.h>
1010 #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"
1611 #include "fw/img.h"
1712 #include "iwl-trans.h"
1813
@@ -44,6 +39,7 @@ · 25 unmodified lines
4439 #define ACPI_SAR_NUM_SUB_BANDS_REV0 5
4540 #define ACPI_SAR_NUM_SUB_BANDS_REV1 11
4641 #define ACPI_SAR_NUM_SUB_BANDS_REV2 11
42+#define ACPI_SAR_NUM_SUB_BANDS_REV3 12
4743
4844 #define ACPI_WRDS_WIFI_DATA_SIZE_REV0 (ACPI_SAR_NUM_CHAINS_REV0 * \
4945 ACPI_SAR_NUM_SUB_BANDS_REV0 + 2)
@@ -51,6 +47,8 @@ · 1 unmodified line
5147 ACPI_SAR_NUM_SUB_BANDS_REV1 + 2)
5248 #define ACPI_WRDS_WIFI_DATA_SIZE_REV2 (ACPI_SAR_NUM_CHAINS_REV2 * \
5349 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)
5452 #define ACPI_EWRD_WIFI_DATA_SIZE_REV0 ((ACPI_SAR_PROFILE_NUM - 1) * \
5553 ACPI_SAR_NUM_CHAINS_REV0 * \
5654 ACPI_SAR_NUM_SUB_BANDS_REV0 + 3)
@@ -60,11 +58,15 @@ · 3 unmodified lines
6058 #define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
6159 ACPI_SAR_NUM_CHAINS_REV2 * \
6260 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)
6364 #define ACPI_WPFC_WIFI_DATA_SIZE 5 /* domain and 4 filter config words */
6465
6566 /* revision 0 and 1 are identical, except for the semantics in the FW */
6667 #define ACPI_GEO_NUM_BANDS_REV0 2
6768 #define ACPI_GEO_NUM_BANDS_REV2 3
69+#define ACPI_GEO_NUM_BANDS_REV4 4
6870
6971 #define ACPI_WRDD_WIFI_DATA_SIZE 2
7072 #define ACPI_SPLC_WIFI_DATA_SIZE 2
@@ -96,10 +98,18 @@ · 25 unmodified lines
9698 */
9799 #define ACPI_WTAS_WIFI_DATA_SIZE (3 + IWL_WTAS_BLACK_LIST_MAX)
98100
99−#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \
100− IWL_NUM_SUB_BANDS_V1) + 2)
101−#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \
102− IWL_NUM_SUB_BANDS_V2) + 2)
101+#define ACPI_PPAG_NUM_CHAINS 2
102+#define ACPI_PPAG_NUM_BANDS_V1 5
103+#define ACPI_PPAG_NUM_BANDS_V2 11
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)
103113
104114 #define IWL_SAR_ENABLE_MSK BIT(0)
105115 #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
5656 RFH_QUEUE_CONFIG_CMD = 0xD,
5757
5858 /**
59− * @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd_v4
59+ * @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd_v4 or
60+ * &struct iwl_tlc_config_cmd_v5 or &struct iwl_tlc_config_cmd.
6061 */
6162 TLC_MNG_CONFIG_CMD = 0xF,
6263
drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h+156−11
@@ -1,6 +1,6 @@
11 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
22 /*
3− * Copyright (C) 2012-2014, 2018-2019, 2021-2025 Intel Corporation
3+ * Copyright (C) 2012-2014, 2018-2019, 2021-2026 Intel Corporation
44 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
55 * Copyright (C) 2016-2017 Intel Deutschland GmbH
66 */
@@ -26,7 +26,7 @@ enum iwl_mac_conf_subcmd_ids { · 19 unmodified lines
2626 */
2727 MISSED_VAP_NOTIF = 0xFA,
2828 /**
29− * @SESSION_PROTECTION_CMD: &struct iwl_mvm_session_prot_cmd
29+ * @SESSION_PROTECTION_CMD: &struct iwl_session_prot_cmd
3030 */
3131 SESSION_PROTECTION_CMD = 0x5,
3232 /**
@@ -34,7 +34,8 @@ enum iwl_mac_conf_subcmd_ids { · 1 unmodified line
3434 */
3535 CANCEL_CHANNEL_SWITCH_CMD = 0x6,
3636 /**
37− * @MAC_CONFIG_CMD: &struct iwl_mac_config_cmd
37+ * @MAC_CONFIG_CMD: &struct iwl_mac_config_cmd_v3 or
38+ * &struct iwl_mac_config_cmd
3839 */
3940 MAC_CONFIG_CMD = 0x8,
4041 /**
@@ -42,7 +43,8 @@ enum iwl_mac_conf_subcmd_ids { · 1 unmodified line
4243 */
4344 LINK_CONFIG_CMD = 0x9,
4445 /**
45− * @STA_CONFIG_CMD: &struct iwl_sta_cfg_cmd
46+ * @STA_CONFIG_CMD: &struct iwl_sta_cfg_cmd_v1,
47+ * &struct iwl_sta_cfg_cmd_v2, or &struct iwl_sta_cfg_cmd
4648 */
4749 STA_CONFIG_CMD = 0xA,
4850 /**
@@ -356,7 +358,7 @@ struct iwl_mac_wifi_gen_support { · 307 unmodified lines
356358 } __packed;
357359
358360 /**
359− * struct iwl_mac_config_cmd - command structure to configure MAC contexts in
361+ * struct iwl_mac_config_cmd_v3 - command structure to configure MAC contexts in
360362 * MLD API for versions 2 and 3
361363 * ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
362364 *
@@ -375,7 +377,7 @@ struct iwl_mac_wifi_gen_support { · 12 unmodified lines
375377 * @client: client mac data
376378 * @p2p_dev: mac data for p2p device
377379 */
378−struct iwl_mac_config_cmd {
380+struct iwl_mac_config_cmd_v3 {
379381 __le32 id_and_color;
380382 __le32 action;
381383 /* MAC_CONTEXT_TYPE_API_E */
@@ -393,7 +395,62 @@ struct iwl_mac_config_cmd { · 11 unmodified lines
393395 struct iwl_mac_client_data client;
394396 struct iwl_mac_p2p_dev_data p2p_dev;
395397 };
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+ */
405+struct 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+ */
434+struct 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 */
397454
398455 /**
399456 * 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
652709 */
653710 #define IWL_FW_MAX_ACTIVE_LINKS_NUM 2
654711 #define IWL_FW_MAX_LINK_ID 3
712+#define IWL_FW_MAX_LINKS IWL_FW_MAX_LINK_ID + 1
655713
656714 /**
657715 * enum iwl_fw_sta_type - FW station types
@@ -662,6 +720,13 @@ struct iwl_link_config_cmd { · 4 unmodified lines
662720 * @STATION_TYPE_MCAST: the station used for BCAST / MCAST in GO. Will be
663721 * suspended / resumed at the right timing depending on the clients'
664722 * 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
665730 * @STATION_TYPE_AUX: aux sta. In the FW there is no need for a special type
666731 * for the aux sta, so this type is only for driver - internal use.
667732 */
@@ -669,8 +734,11 @@ enum iwl_fw_sta_type { · 1 unmodified line
669734 STATION_TYPE_PEER,
670735 STATION_TYPE_BCAST_MGMT,
671736 STATION_TYPE_MCAST,
672− STATION_TYPE_AUX,
673−}; /* STATION_TYPE_E_VER_1 */
737+ STATION_TYPE_NAN_PEER_NMI,
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 */
674742
675743 /**
676744 * 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
729797 } __packed; /* STA_CMD_API_S_VER_1 */
730798
731799 /**
732− * struct iwl_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
800+ * struct iwl_sta_cfg_cmd_v2 - cmd structure to add a peer sta to the uCode's
733801 * station table
734802 * ( STA_CONFIG_CMD = 0xA )
735803 *
@@ -769,7 +837,7 @@ struct iwl_sta_cfg_cmd_v1 { · 33 unmodified lines
769837 * @mic_compute_pad_delay: MIC compute time padding
770838 * @reserved: Reserved for alignment
771839 */
772−struct iwl_sta_cfg_cmd {
840+struct iwl_sta_cfg_cmd_v2 {
773841 __le32 sta_id;
774842 __le32 link_id;
775843 u8 peer_mld_address[ETH_ALEN];
@@ -799,6 +867,83 @@ struct iwl_sta_cfg_cmd { · 23 unmodified lines
799867 u8 reserved[2];
800868 } __packed; /* STA_CMD_API_S_VER_2 */
801869
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+ */
914+struct 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+
802947 /**
803948 * struct iwl_aux_sta_cmd - command for AUX STA configuration
804949 * ( 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
5757 * @FW_MAC_TYPE_P2P_DEVICE: P2P Device
5858 * @FW_MAC_TYPE_P2P_STA: P2P client
5959 * @FW_MAC_TYPE_GO: P2P GO
60− * @FW_MAC_TYPE_TEST: ?
61− * @FW_MAC_TYPE_MAX: highest support MAC type
60+ * @FW_MAC_TYPE_NAN: NAN (since version 4)
6261 */
6362 enum iwl_mac_types {
6463 FW_MAC_TYPE_FIRST = 1,
@@ -70,8 +69,7 @@ enum iwl_mac_types { · 5 unmodified lines
7069 FW_MAC_TYPE_P2P_DEVICE,
7170 FW_MAC_TYPE_P2P_STA,
7271 FW_MAC_TYPE_GO,
73− FW_MAC_TYPE_TEST,
74− FW_MAC_TYPE_MAX = FW_MAC_TYPE_TEST
72+ FW_MAC_TYPE_NAN,
7573 }; /* MAC_CONTEXT_TYPE_API_E_VER_1 */
7674
7775 /**
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
204204 } __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
205205
206206 #define IWL_NUM_CHANNELS_V1 51
207−#define IWL_NUM_CHANNELS 110
207+#define IWL_NUM_CHANNELS_V2 110
208208
209209 /**
210210 * struct iwl_nvm_get_info_regulatory_v1 - regulatory information
@@ -227,7 +227,7 @@ struct iwl_nvm_get_info_regulatory_v1 { · 16 unmodified lines
227227 struct iwl_nvm_get_info_regulatory {
228228 __le32 lar_enabled;
229229 __le32 n_channels;
230− __le32 channel_profile[IWL_NUM_CHANNELS];
230+ __le32 channel_profile[IWL_NUM_CHANNELS_V2];
231231 } __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */
232232
233233 /**
@@ -701,13 +701,23 @@ struct iwl_pnvm_init_complete_ntfy { · 467 unmodified lines
701701 #define UATS_TABLE_COL_SIZE 13
702702
703703 /**
704− * struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD
704+ * struct iwl_mcc_allowed_ap_type_cmd_v1 - struct for MCC_ALLOWED_AP_TYPE_CMD
705705 * @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS)
706706 * @reserved: reserved
707707 */
708−struct iwl_mcc_allowed_ap_type_cmd {
708+struct iwl_mcc_allowed_ap_type_cmd_v1 {
709709 u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
710710 __le16 reserved;
711711 } __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_1 */
712712
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+ */
718+struct 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+
713723 #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
269269 #define IWL_NUM_CHAIN_LIMITS 2
270270 #define IWL_NUM_SUB_BANDS_V1 5
271271 #define IWL_NUM_SUB_BANDS_V2 11
272+#define IWL_NUM_SUB_BANDS_V3 12
272273
273274 /**
274275 * 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
425426 __le32 flags;
426427 } __packed; /* TX_REDUCED_POWER_API_S_VER_10 */
427428
429+struct 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+
428437 /*
429438 * struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
430439 * @common: common part of the command
431440 * @v9: version 9 part of the command
432441 * @v10: version 10 part of the command
442+ * @v11: version 11 part of the command
433443 */
434444 struct iwl_dev_tx_power_cmd {
435445 struct iwl_dev_tx_power_common common;
436446 union {
437447 struct iwl_dev_tx_power_cmd_v9 v9;
438448 struct iwl_dev_tx_power_cmd_v10 v10;
449+ struct iwl_dev_tx_power_cmd_v11 v11;
439450 };
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+ */
441455
442456 #define IWL_NUM_GEO_PROFILES 3
443457 #define IWL_NUM_GEO_PROFILES_V3 8
444458 #define IWL_NUM_BANDS_PER_CHAIN_V1 2
445459 #define IWL_NUM_BANDS_PER_CHAIN_V2 3
460+#define IWL_NUM_BANDS_PER_CHAIN_V6 4
446461
447462 /**
448463 * 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
524539 __le32 table_revision;
525540 } __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */
526541
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+ */
548+struct 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+
527554 union iwl_geo_tx_power_profiles_cmd {
528555 struct iwl_geo_tx_power_profiles_cmd_v1 v1;
529556 struct iwl_geo_tx_power_profiles_cmd_v2 v2;
530557 struct iwl_geo_tx_power_profiles_cmd_v3 v3;
531558 struct iwl_geo_tx_power_profiles_cmd_v4 v4;
532559 struct iwl_geo_tx_power_profiles_cmd_v5 v5;
560+ struct iwl_geo_tx_power_profiles_cmd_v6 v6;
533561 };
534562
535563 /**
@@ -573,6 +601,7 @@ enum iwl_ppag_flags { · 37 unmodified lines
573601 * @v1: command version 1 structure.
574602 * @v5: command version 5 structure.
575603 * @v7: command version 7 structure.
604+ * @v8: command version 8 structure.
576605 * @v1.flags: values from &enum iwl_ppag_flags
577606 * @v1.gain: table of antenna gain values per chain and sub-band
578607 * @v1.reserved: reserved
@@ -581,6 +610,8 @@ enum iwl_ppag_flags { · 2 unmodified lines
581610 * @v7.ppag_config_info: see @struct bios_value_u32
582611 * @v7.gain: table of antenna gain values per chain and sub-band
583612 * @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
584615 */
585616 union iwl_ppag_table_cmd {
586617 struct {
@@ -598,6 +629,10 @@ union iwl_ppag_table_cmd { · 11 unmodified lines
598629 s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
599630 s8 reserved[2];
600631 } __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 */
601636 } __packed;
602637
603638 #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
985985 } __packed; /* SCAN_PROBE_PARAMS_API_S_VER_4 */
986986
987987 #define SCAN_MAX_NUM_CHANS_V3 67
988+#define SCAN_MAX_NUM_CHANS_V4 68
988989
989990 /**
990991 * struct iwl_scan_channel_params_v4 - channel params
@@ -1027,6 +1028,24 @@ struct iwl_scan_channel_params_v7 { · 36 unmodified lines
10271028 struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V3];
10281029 } __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */
10291030
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+ */
1042+struct 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+
10301049 /**
10311050 * struct iwl_scan_general_params_v11 - channel params
10321051 * @flags: &enum iwl_umac_scan_general_flags_v2
@@ -1109,6 +1128,20 @@ struct iwl_scan_req_params_v17 { · 76 unmodified lines
11091128 struct iwl_scan_probe_params_v4 probe_params;
11101129 } __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */
11111130
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+ */
1138+struct 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+
11121145 /**
11131146 * struct iwl_scan_req_umac_v12 - scan request command (v12)
11141147 * @uid: scan id, &enum iwl_umac_scan_uid_offsets
@@ -1133,6 +1166,18 @@ struct iwl_scan_req_umac_v17 { · 18 unmodified lines
11331166 struct iwl_scan_req_params_v17 scan_params;
11341167 } __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */
11351168
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+ */
1175+struct 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+
11361181 /**
11371182 * struct iwl_umac_scan_abort - scan abort command
11381183 * @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
598598 } __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */
599599
600600 #define IWL_STATS_MAX_PHY_OPERATIONAL 3
601−#define IWL_STATS_MAX_FW_LINKS (IWL_FW_MAX_LINK_ID + 1)
602601
603602 /**
604603 * struct iwl_system_statistics_notif_oper - statistics notification
@@ -610,7 +609,7 @@ struct iwl_stats_ntfy_per_sta { · 5 unmodified lines
610609 */
611610 struct iwl_system_statistics_notif_oper {
612611 __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];
614613 struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
615614 struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];
616615 } __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */
@@ -624,7 +623,7 @@ struct iwl_system_statistics_notif_oper { · 7 unmodified lines
624623 */
625624 struct iwl_system_statistics_part1_notif_oper {
626625 __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];
628627 __le32 per_phy_crc_error_stats[IWL_STATS_MAX_PHY_OPERATIONAL];
629628 } __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_API_S_VER_4 */
630629
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
29332933 IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",
29342934 le32_to_cpu(desc->trig_desc.type));
29352935
2936− queue_delayed_work(system_unbound_wq, &wk_data->wk,
2936+ queue_delayed_work(system_dfl_wq, &wk_data->wk,
29372937 usecs_to_jiffies(delay));
29382938
29392939 return 0;
@@ -3236,7 +3236,7 @@ int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, · 296 unmodified lines
32363236 if (sync)
32373237 iwl_fw_dbg_collect_sync(fwrt, idx);
32383238 else
3239− queue_delayed_work(system_unbound_wq,
3239+ queue_delayed_work(system_dfl_wq,
32403240 &fwrt->dump.wks[idx].wk,
32413241 usecs_to_jiffies(delay));
32423242
drivers/net/wireless/intel/iwlwifi/fw/dump.c+1−68
@@ -1,6 +1,6 @@
11 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22 /*
3− * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
3+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
44 * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
55 * Copyright (C) 2015-2017 Intel Deutschland GmbH
66 */
@@ -128,19 +128,11 @@ static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt) · 121 unmodified lines
128128
129129 IWL_ERR(fwrt, "0x%08X | %s\n", table.error_id,
130130 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);
134131 IWL_ERR(fwrt, "0x%08X | umac interruptlink2\n", table.ilink2);
135132 IWL_ERR(fwrt, "0x%08X | umac data1\n", table.data1);
136133 IWL_ERR(fwrt, "0x%08X | umac data2\n", table.data2);
137134 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);
142135 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);
144136 }
145137
146138 static 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
200192
201193 IWL_ERR(fwrt, "0x%08X | %-28s\n", table.error_id,
202194 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);
207195 IWL_ERR(fwrt, "0x%08X | interruptlink2\n", table.ilink2);
208196 IWL_ERR(fwrt, "0x%08X | data1\n", table.data1);
209197 IWL_ERR(fwrt, "0x%08X | data2\n", table.data2);
210198 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);
236199 }
237200
238201 /*
@@ -264,7 +227,6 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt, int idx) · 25 unmodified lines
264227 struct iwl_trans *trans = fwrt->trans;
265228 struct iwl_tcm_error_event_table table = {};
266229 u32 base = fwrt->trans->dbg.tcm_error_event_table[idx];
267− int i;
268230 u32 flag = idx ? IWL_ERROR_EVENT_TABLE_TCM2 :
269231 IWL_ERROR_EVENT_TABLE_TCM1;
270232
@@ -275,23 +237,10 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt, int idx) · 4 unmodified lines
275237
276238 IWL_ERR(fwrt, "TCM%d status:\n", idx + 1);
277239 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);
280240 IWL_ERR(fwrt, "0x%08X | tcm interruptlink2\n", table.ilink2);
281241 IWL_ERR(fwrt, "0x%08X | tcm data1\n", table.data1);
282242 IWL_ERR(fwrt, "0x%08X | tcm data2\n", table.data2);
283243 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);
295244 }
296245
297246 /*
@@ -338,26 +287,10 @@ static void iwl_fwrt_dump_rcm_error_log(struct iwl_fw_runtime *fwrt, int idx) · 40 unmodified lines
338287
339288 IWL_ERR(fwrt, "RCM%d status:\n", idx + 1);
340289 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);
343290 IWL_ERR(fwrt, "0x%08X | rcm interruptlink2\n", table.ilink2);
344291 IWL_ERR(fwrt, "0x%08X | rcm data1\n", table.data1);
345292 IWL_ERR(fwrt, "0x%08X | rcm data2\n", table.data2);
346293 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);
361294 }
362295
363296 static 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
103103 IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
104104 IWL_UCODE_TLV_CURRENT_PC = 68,
105105 IWL_UCODE_TLV_FSEQ_BIN_VERSION = 72,
106+ IWL_UCODE_TLV_CMD_BIOS_TABLE = 73,
106107
107108 /* contains sub-sections like PNVM file does (did) */
108109 IWL_UCODE_TLV_PNVM_DATA = 74,
@@ -1040,6 +1041,20 @@ struct iwl_fw_cmd_version { · 931 unmodified lines
10401041 u8 notif_ver;
10411042 } __packed;
10421043
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+ */
1051+struct iwl_fw_cmd_bios_table {
1052+ u8 cmd;
1053+ u8 group;
1054+ u8 max_acpi_revision;
1055+ u8 max_uefi_revision;
1056+} __packed;
1057+
10431058 struct iwl_fw_tcm_error_addr {
10441059 __le32 addr;
10451060 }; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */
drivers/net/wireless/intel/iwlwifi/fw/img.c+31−1
@@ -1,11 +1,41 @@
11 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22 /*
33 * Copyright(c) 2019 - 2021 Intel Corporation
4− * Copyright(c) 2024 Intel Corporation
4+ * Copyright(c) 2024 - 2025 Intel Corporation
55 */
66 #include <fw/api/commands.h>
77 #include "img.h"
88
9+u8 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+}
37+EXPORT_SYMBOL_GPL(iwl_fw_lookup_cmd_bios_supported_revision);
38+
939 u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def)
1040 {
1141 const struct iwl_fw_cmd_version *entry;
drivers/net/wireless/intel/iwlwifi/fw/img.h+8−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include <linux/types.h>
1010
1111 #include "api/dbg-tlv.h"
12+#include "api/nvm-reg.h"
1213
1314 #include "file.h"
1415 #include "error-dump.h"
@@ -57,6 +58,9 @@ struct iwl_ucode_capabilities { · 42 unmodified lines
5758
5859 const struct iwl_fw_cmd_version *cmd_versions;
5960 u32 n_cmd_versions;
61+
62+ const struct iwl_fw_cmd_bios_table *cmd_bios_tables;
63+ u32 n_cmd_bios_tables;
6064 };
6165
6266 static inline bool
@@ -274,6 +278,10 @@ iwl_get_ucode_image(const struct iwl_fw *fw, enum iwl_ucode_type ucode_type) · 211 unmodified lines
274278 return &fw->img[ucode_type];
275279 }
276280
281+u8 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+
277285 u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def);
278286
279287 u8 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
241241 int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };
242242 int i, j;
243243
244+ if (WARN_ON_ONCE(n_subbands >
245+ ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands)))
246+ return -EINVAL;
247+
244248 for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) {
245249 struct iwl_sar_profile *prof;
246250
@@ -300,132 +304,6 @@ int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt, · 53 unmodified lines
300304 }
301305 IWL_EXPORT_SYMBOL(iwl_sar_fill_profile);
302306
303−static 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 */
319−int 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−}
427−IWL_EXPORT_SYMBOL(iwl_fill_ppag_table);
428−
429307 bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)
430308 {
431309 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
440318 }
441319 IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);
442320
321+/* Print the PPAG table as read from BIOS */
322+void 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+
443342 bool iwl_is_tas_approved(void)
444343 {
445344 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
2121 */
2222 #define BIOS_SAR_MAX_CHAINS_PER_PROFILE 4
2323 #define BIOS_SAR_NUM_CHAINS 2
24−#define BIOS_SAR_MAX_SUB_BANDS_NUM 11
24+#define BIOS_SAR_MAX_SUB_BANDS_NUM 12
25+#define BIOS_PPAG_MAX_SUB_BANDS_NUM 12
2526
2627 #define BIOS_GEO_NUM_CHAINS 2
27−#define BIOS_GEO_MAX_NUM_BANDS 3
28+#define BIOS_GEO_MAX_NUM_BANDS 4
2829 #define BIOS_GEO_MAX_PROFILE_NUM 8
2930 #define BIOS_GEO_MIN_PROFILE_NUM 3
3031
@@ -100,7 +101,7 @@ struct iwl_geo_profile { · 69 unmodified lines
100101
101102 /* Same thing as with SAR, all revisions fit in revision 2 */
102103 struct iwl_ppag_chain {
103− s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
104+ s8 subbands[BIOS_PPAG_MAX_SUB_BANDS_NUM];
104105 };
105106
106107 struct iwl_tas_data {
@@ -180,6 +181,9 @@ enum iwl_dsm_masks_reg { · 73 unmodified lines
180181
181182 struct iwl_fw_runtime;
182183
184+/* Print the PPAG table as read from BIOS */
185+void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands);
186+
183187 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
184188
185189 int 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
190194 __le16 *per_chain, u32 n_tables, u32 n_subbands,
191195 int prof_a, int prof_b);
192196
193−int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
194− union iwl_ppag_table_cmd *cmd,
195− int *cmd_size);
196−
197197 bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
198198
199199 bool 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
106106 * @cur_fw_img: current firmware image, must be maintained by
107107 * the driver by calling &iwl_fw_set_current_image()
108108 * @dump: debug dump data
109− * @uats_table: AP type table
110− * @uats_valid: is AP type table valid
109+ * @ap_type_cmd: AP type tables (for enablement on 6 GHz)
110+ * @ap_type_cmd_valid: if &ap_type_cmd is valid
111111 * @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock:
112112 * 0: Unlocked, 1 and 2: Locked.
113113 * Only read the UEFI variables if locked.
114114 * @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables
115115 * @geo_profiles: geographic profiles as read from WGDS BIOS table
116+ * @geo_bios_source: see &enum bios_source
116117 * @phy_filters: specific phy filters as read from WPFC BIOS table
117118 * @ppag_bios_rev: PPAG BIOS revision
118119 * @ppag_bios_source: see &enum bios_source
@@ -204,6 +205,7 @@ struct iwl_fw_runtime { · 85 unmodified lines
204205 u8 sar_chain_b_profile;
205206 u8 reduced_power_flags;
206207 struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
208+ enum bios_source geo_bios_source;
207209 u32 geo_rev;
208210 u32 geo_num_profiles;
209211 bool geo_enabled;
@@ -213,8 +215,8 @@ struct iwl_fw_runtime { · 3 unmodified lines
213215 u8 ppag_bios_source;
214216 struct iwl_sar_offset_mapping_cmd sgom_table;
215217 bool sgom_enabled;
216− struct iwl_mcc_allowed_ap_type_cmd uats_table;
217− bool uats_valid;
218+ struct iwl_mcc_allowed_ap_type_cmd ap_type_cmd;
219+ bool ap_type_cmd_valid;
218220 u8 uefi_tables_lock_status;
219221 struct iwl_phy_specific_cfg phy_filters;
220222 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
402402 if (uats_data->revision != 1)
403403 return -EINVAL;
404404
405− memcpy(fwrt->uats_table.mcc_to_ap_type_map,
405+ memcpy(fwrt->ap_type_cmd.mcc_to_ap_type_map,
406406 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));
408408
409− fwrt->uats_valid = true;
409+ fwrt->ap_type_cmd_valid = true;
410410
411411 return 0;
412412 }
@@ -429,12 +429,61 @@ void iwl_uefi_get_uats_table(struct iwl_trans *trans, · 16 unmodified lines
429429 }
430430 IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table);
431431
432+void 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+
457+out:
458+ kfree(data);
459+}
460+IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table);
461+
432462 static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,
433− struct uefi_sar_profile *uefi_sar_prof,
434− u8 prof_index, bool enabled)
463+ const u8 *vals, u8 prof_index,
464+ u8 num_subbands, bool enabled)
435465 {
436− memcpy(&fwrt->sar_profiles[prof_index].chains, uefi_sar_prof,
437− sizeof(struct uefi_sar_profile));
466+ struct iwl_sar_profile *sar_prof = &fwrt->sar_profiles[prof_index];
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+ }
438487
439488 fwrt->sar_profiles[prof_index].enabled = enabled & IWL_SAR_ENABLE_MSK;
440489 }
@@ -442,24 +491,46 @@ static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt, · 1 unmodified line
442491 int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
443492 {
444493 struct uefi_cnv_var_wrds *data;
494+ unsigned long size;
495+ unsigned long expected_size;
496+ int num_subbands;
445497 int ret = 0;
446498
447499 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+
449504 if (IS_ERR(data))
450505 return -EINVAL;
451506
452− if (data->revision != IWL_UEFI_WRDS_REVISION) {
453− ret = -EINVAL;
454− IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WRDS revision:%d\n",
507+ switch (data->revision) {
508+ case 2:
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",
455519 data->revision);
520+ ret = -EINVAL;
521+ goto out;
522+ }
523+
524+ if (size != expected_size) {
525+ ret = -EINVAL;
456526 goto out;
457527 }
458528
459529 /* The profile from WRDS is officially profile 1, but goes
460530 * into sar_profiles[0] (because we don't have a profile 0).
461531 */
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);
463534 out:
464535 kfree(data);
465536 return ret;
@@ -468,21 +539,40 @@ out: · 2 unmodified lines
468539 int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
469540 {
470541 struct uefi_cnv_var_ewrd *data;
542+ unsigned long expected_size;
471543 int i, ret = 0;
544+ unsigned long size;
545+ int num_subbands;
546+ int profile_size;
472547
473548 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);
475552 if (IS_ERR(data))
476553 return -EINVAL;
477554
478− if (data->revision != IWL_UEFI_EWRD_REVISION) {
479− ret = -EINVAL;
480− IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI EWRD revision:%d\n",
555+ switch (data->revision) {
556+ case 2:
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",
481569 data->revision);
570+ ret = -EINVAL;
482571 goto out;
483572 }
484573
485− if (data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {
574+ if (size != expected_size ||
575+ data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {
486576 ret = -EINVAL;
487577 goto out;
488578 }
@@ -492,8 +582,8 @@ int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt) · 3 unmodified lines
492582 * save them in sar_profiles[1-3] (because we don't
493583 * have profile 0). So in the array we start from 1.
494584 */
495− iwl_uefi_set_sar_profile(fwrt, &data->sar_profiles[i], i + 1,
496− data->mode);
585+ iwl_uefi_set_sar_profile(fwrt, &data->vals[i * profile_size],
586+ i + 1, num_subbands, data->mode);
497587
498588 out:
499589 kfree(data);
@@ -503,20 +593,39 @@ out: · 3 unmodified lines
503593 int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
504594 {
505595 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;
507601
508602 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);
510605 if (IS_ERR(data))
511606 return -EINVAL;
512607
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:
514618 ret = -EINVAL;
515619 IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WGDS revision:%d\n",
516620 data->revision);
517621 goto out;
518622 }
519623
624+ if (size != expected_size) {
625+ ret = -EINVAL;
626+ goto out;
627+ }
628+
520629 if (data->num_profiles < BIOS_GEO_MIN_PROFILE_NUM ||
521630 data->num_profiles > BIOS_GEO_MAX_PROFILE_NUM) {
522631 ret = -EINVAL;
@@ -525,10 +634,31 @@ int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt) · 2 unmodified lines
525634 goto out;
526635 }
527636
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+
528646 fwrt->geo_rev = data->revision;
529− for (i = 0; i < data->num_profiles; i++)
530− memcpy(&fwrt->geo_profiles[i], &data->geo_profiles[i],
531− sizeof(struct iwl_geo_profile));
647+ fwrt->geo_bios_source = BIOS_SOURCE_UEFI;
648+ profile_size = 3 * n_subbands;
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+ }
532662
533663 fwrt->geo_num_profiles = data->num_profiles;
534664 fwrt->geo_enabled = true;
@@ -540,28 +670,66 @@ out: · 5 unmodified lines
540670 int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
541671 {
542672 struct uefi_cnv_var_ppag *data;
673+ int n_subbands;
674+ u32 valid_rev;
543675 int ret = 0;
544676
545677 data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME,
546− "PPAG", sizeof(*data), NULL);
547− if (IS_ERR(data))
548− return -EINVAL;
678+ "PPAG", UEFI_PPAG_DATA_SIZE_V5,
679+ NULL);
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+ }
549699
550− if (data->revision < IWL_UEFI_MIN_PPAG_REV ||
551− data->revision > IWL_UEFI_MAX_PPAG_REV) {
700+ return -EINVAL;
701+
702+parse_table:
703+ if (!(BIT(data->revision) & valid_rev)) {
552704 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",
554707 data->revision);
555708 goto out;
556709 }
557710
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+
558722 fwrt->ppag_bios_rev = data->revision;
559723 fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes,
560724 fwrt->ppag_bios_rev);
561725
562− BUILD_BUG_ON(sizeof(fwrt->ppag_chains) != sizeof(data->ppag_chains));
563− memcpy(&fwrt->ppag_chains, &data->ppag_chains,
564− sizeof(data->ppag_chains));
726+ for (int chain = 0; chain < UEFI_PPAG_NUM_CHAINS; chain++) {
727+ for (int subband = 0; subband < n_subbands; subband++)
728+ fwrt->ppag_chains[chain].subbands[subband] =
729+ data->vals[chain * n_subbands + subband];
730+ }
731+
732+ iwl_bios_print_ppag(fwrt, n_subbands);
565733 fwrt->ppag_bios_source = BIOS_SOURCE_UEFI;
566734 out:
567735 kfree(data);
drivers/net/wireless/intel/iwlwifi/fw/uefi.h+110−31
@@ -25,16 +25,12 @@ · 24 unmodified lines
2525 #define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing"
2626 #define IWL_UEFI_DSBR_NAME L"UefiCnvCommonDSBR"
2727 #define IWL_UEFI_WPFC_NAME L"WPFC"
28+#define IWL_UEFI_UNEB_NAME L"CnvUefiWlanUNEB"
2829
2930
3031 #define IWL_SGOM_MAP_SIZE 339
3132 #define IWL_UATS_MAP_SIZE 339
3233
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
3834 #define IWL_UEFI_MIN_WTAS_REVISION 1
3935 #define IWL_UEFI_MAX_WTAS_REVISION 2
4036 #define IWL_UEFI_SPLC_REVISION 0
@@ -63,6 +59,9 @@ struct uefi_cnv_wlan_uats_data { · 22 unmodified lines
6359 u8 mcc_to_ap_type_map[IWL_UATS_MAP_SIZE - 1];
6460 } __packed;
6561
62+/* UNEB's layout is identical to UATS's */
63+#define uefi_cnv_wlan_uneb_data uefi_cnv_wlan_uats_data
64+
6665 struct uefi_cnv_common_step_data {
6766 u8 revision;
6867 u8 step_mode;
@@ -72,68 +71,135 @@ struct uefi_cnv_common_step_data { · 3 unmodified lines
7271 u8 radio2;
7372 } __packed;
7473
75−/*
76− * struct uefi_sar_profile - a SAR profile as defined in UEFI
77− *
78− * @chains: a per-chain table of SAR values
79− */
80−struct uefi_sar_profile {
81− struct iwl_sar_profile_chain chains[BIOS_SAR_MAX_CHAINS_PER_PROFILE];
82−} __packed;
74+#define UEFI_PPAG_SUB_BANDS_NUM_REV4 11
75+#define UEFI_PPAG_SUB_BANDS_NUM_REV5 12
76+#define UEFI_PPAG_NUM_CHAINS 2
8377
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+/**
8587 * struct uefi_cnv_var_wrds - WRDS table as defined in UEFI
8688 *
8789 * @revision: the revision of the table
8890 * @mode: is WRDS enbaled/disabled
89− * @sar_profile: sar profile #1
91+ * @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
9097 */
9198 struct uefi_cnv_var_wrds {
9299 u8 revision;
93100 u32 mode;
94− struct uefi_sar_profile sar_profile;
101+ u8 vals[];
95102 } __packed;
96103
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+/**
98121 * struct uefi_cnv_var_ewrd - EWRD table as defined in UEFI
99122 * @revision: the revision of the table
100123 * @mode: is WRDS enbaled/disabled
101124 * @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.
103129 */
104130 struct uefi_cnv_var_ewrd {
105131 u8 revision;
106132 u32 mode;
107133 u32 num_profiles;
108− struct uefi_sar_profile sar_profiles[BIOS_SAR_MAX_PROFILE_NUM - 1];
134+ u8 vals[];
109135 } __packed;
110136
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+/**
112146 * struct uefi_cnv_var_wgds - WGDS table as defined in UEFI
113147 * @revision: the revision of the table
114148 * @num_profiles: the number of geo profiles we have in the table.
115149 * 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.
117155 */
118156 struct uefi_cnv_var_wgds {
119157 u8 revision;
120158 u8 num_profiles;
121− struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
159+ u8 vals[];
122160 } __packed;
123161
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+/**
125178 * struct uefi_cnv_var_ppag - PPAG table as defined in UEFI
126179 * @revision: the revision of the table
127180 * @ppag_modes: values from &enum iwl_ppag_flags
128− * @ppag_chains: the PPAG values per chain and band
181+ * @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
129187 */
130188 struct uefi_cnv_var_ppag {
131189 u8 revision;
132190 u32 ppag_modes;
133− struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
191+ s8 vals[];
134192 } __packed;
135193
136−/* struct uefi_cnv_var_wtas - WTAS tabled as defined in UEFI
194+#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
137203 * @revision: the revision of the table
138204 * @tas_selection: different options of TAS enablement.
139205 * @black_list_size: the number of defined entried in the black list
@@ -146,7 +212,8 @@ struct uefi_cnv_var_wtas { · 6 unmodified lines
146212 u16 black_list[IWL_WTAS_BLACK_LIST_MAX];
147213 } __packed;
148214
149−/* struct uefi_cnv_var_splc - SPLC tabled as defined in UEFI
215+/**
216+ * struct uefi_cnv_var_splc - SPLC tabled as defined in UEFI
150217 * @revision: the revision of the table
151218 * @default_pwr_limit: The default maximum power per device
152219 */
@@ -155,7 +222,8 @@ struct uefi_cnv_var_splc { · 2 unmodified lines
155222 u32 default_pwr_limit;
156223 } __packed;
157224
158−/* struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI
225+/**
226+ * struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI
159227 * @revision: the revision of the table
160228 * @mcc: country identifier as defined in ISO/IEC 3166-1 Alpha 2 code
161229 */
@@ -164,7 +232,8 @@ struct uefi_cnv_var_wrdd { · 2 unmodified lines
164232 u32 mcc;
165233 } __packed;
166234
167−/* struct uefi_cnv_var_eckv - ECKV table as defined in UEFI
235+/**
236+ * struct uefi_cnv_var_eckv - ECKV table as defined in UEFI
168237 * @revision: the revision of the table
169238 * @ext_clock_valid: indicates if external 32KHz clock is valid
170239 */
@@ -175,7 +244,8 @@ struct uefi_cnv_var_eckv { · 4 unmodified lines
175244
176245 #define UEFI_MAX_DSM_FUNCS 32
177246
178−/* struct uefi_cnv_var_general_cfg - DSM-like table as defined in UEFI
247+/**
248+ * struct uefi_cnv_var_general_cfg - DSM-like table as defined in UEFI
179249 * @revision: the revision of the table
180250 * @functions: payload of the different DSM functions
181251 */
@@ -185,7 +255,9 @@ struct uefi_cnv_var_general_cfg { · 3 unmodified lines
185255 } __packed;
186256
187257 #define IWL_UEFI_WBEM_REV0_MASK (BIT(0) | BIT(1))
188−/* struct uefi_cnv_wlan_wbem_data - Bandwidth enablement per MCC as defined
258+
259+/**
260+ * struct uefi_cnv_wlan_wbem_data - Bandwidth enablement per MCC as defined
189261 * in UEFI
190262 * @revision: the revision of the table
191263 * @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
274346 void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
275347 void iwl_uefi_get_uats_table(struct iwl_trans *trans,
276348 struct iwl_fw_runtime *fwrt);
349+void iwl_uefi_get_uneb_table(struct iwl_trans *trans,
350+ struct iwl_fw_runtime *fwrt);
277351 int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);
278352 int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
279353 int 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
373447 {
374448 }
375449
450+static inline void
451+iwl_uefi_get_uneb_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
452+{
453+}
454+
376455 static inline
377456 int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
378457 {
drivers/net/wireless/intel/iwlwifi/iwl-config.h+0−1
@@ -85,7 +85,6 @@ enum iwl_nvm_type { · 84 unmodified lines
8585 #define IWL_WATCHDOG_DISABLED 0
8686 #define IWL_DEF_WD_TIMEOUT 2500
8787 #define IWL_LONG_WD_TIMEOUT 10000
88−#define IWL_MAX_WD_TIMEOUT 120000
8988
9089 #define IWL_DEFAULT_MAX_TX_POWER 22
9190 #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
133133 kfree(drv->fw.dbg.mem_tlv);
134134 kfree(drv->fw.iml);
135135 kfree(drv->fw.ucode_capa.cmd_versions);
136+ kfree(drv->fw.ucode_capa.cmd_bios_tables);
136137 kfree(drv->fw.phy_integration_ver);
137138 kfree(drv->trans->dbg.pc_data);
138139 drv->trans->dbg.pc_data = NULL;
@@ -1314,7 +1315,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, · 1175 unmodified lines
13141315 if (tlv_len != sizeof(u32))
13151316 goto invalid_tlv_len;
13161317 if (le32_to_cpup((const __le32 *)tlv_data) >
1317− IWL_FW_MAX_LINK_ID + 1) {
1318+ IWL_FW_MAX_LINKS) {
13181319 IWL_ERR(drv,
13191320 "%d is an invalid number of links\n",
13201321 le32_to_cpup((const __le32 *)tlv_data));
@@ -1426,6 +1427,26 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, · 105 unmodified lines
14261427 return -ENOMEM;
14271428 drv->fw.pnvm_size = tlv_len;
14281429 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;
14291450 default:
14301451 IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
14311452 break;
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c+8−1
@@ -23,6 +23,8 @@ · 22 unmodified lines
2323 #include "fw/api/commands.h"
2424 #include "fw/api/cmdhdr.h"
2525 #include "fw/img.h"
26+#include "fw/dbg.h"
27+
2628 #include "mei/iwl-mei.h"
2729
2830 /* NVM offsets (in words) definitions */
@@ -1702,6 +1704,11 @@ iwl_parse_nvm_mcc_info(struct iwl_trans *trans, · 1673 unmodified lines
17021704 band);
17031705 new_rule = false;
17041706
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+
17051712 if (!(ch_flags & NVM_CHANNEL_VALID)) {
17061713 iwl_nvm_print_channel_flags(dev, IWL_DL_LAR,
17071714 nvm_chan[ch_idx], ch_flags);
@@ -2031,7 +2038,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, · 323 unmodified lines
20312038 if (empty_otp)
20322039 IWL_INFO(trans, "OTP is empty\n");
20332040
2034− nvm = kzalloc_flex(*nvm, channels, IWL_NUM_CHANNELS);
2041+ nvm = kzalloc_flex(*nvm, channels, IWL_NUM_CHANNELS_V2);
20352042 if (!nvm) {
20362043 ret = -ENOMEM;
20372044 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
138138 IWL_RESET_MODE_FUNC_RESET,
139139 IWL_RESET_MODE_PROD_RESET,
140140 };
141− static const enum iwl_reset_mode escalation_list_sc[] = {
141+ static const enum iwl_reset_mode escalation_list_top[] = {
142142 IWL_RESET_MODE_SW_RESET,
143143 IWL_RESET_MODE_REPROBE,
144144 IWL_RESET_MODE_REPROBE,
@@ -159,14 +159,14 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans) · 14 unmodified lines
159159
160160 if (trans->request_top_reset) {
161161 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))
163163 return IWL_RESET_MODE_TOP_RESET;
164164 return IWL_RESET_MODE_PROD_RESET;
165165 }
166166
167− if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) {
168− escalation_list = escalation_list_sc;
169− escalation_list_size = ARRAY_SIZE(escalation_list_sc);
167+ if (iwl_trans_is_top_reset_supported(trans)) {
168+ escalation_list = escalation_list_top;
169+ escalation_list_size = ARRAY_SIZE(escalation_list_top);
170170 } else {
171171 escalation_list = escalation_list_old;
172172 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
10881088 */
10891089 trans->restart.during_reset = test_bit(STATUS_IN_SW_RESET,
10901090 &trans->status);
1091− queue_delayed_work(system_unbound_wq, &trans->restart.wk, 0);
1091+ queue_delayed_work(system_dfl_wq, &trans->restart.wk, 0);
10921092 }
10931093
10941094 static 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
12581258
12591259 bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans);
12601260
1261+static 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+
12611279 #endif /* __iwl_trans_h__ */
drivers/net/wireless/intel/iwlwifi/mld/constants.h+0−1
@@ -36,7 +36,6 @@ · 35 unmodified lines
3636 #define IWL_MLD_PS_HEAVY_RX_THLD_PACKETS 8
3737
3838 #define IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC 30
39−#define IWL_MLD_SCAN_EXPIRE_TIME_SEC 20
4039
4140 #define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ)
4241
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
513513 return ret;
514514
515515 iwl_mld_init_tas(mld);
516− iwl_mld_init_uats(mld);
516+ iwl_mld_init_ap_type_tables(mld);
517517
518518 return 0;
519519 }
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
6161 static int iwl_mld_send_mac_cmd(struct iwl_mld *mld,
6262 struct iwl_mac_config_cmd *cmd)
6363 {
64+ u16 cmd_id = WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD);
65+ int len = sizeof(*cmd);
6466 int ret;
6567
6668 lockdep_assert_wiphy(mld->wiphy);
6769
68− ret = iwl_mld_send_cmd_pdu(mld,
69− WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),
70− cmd);
70+ if (iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0) < 4) {
71+ if (WARN_ON(cmd->mac_type == cpu_to_le32(FW_MAC_TYPE_NAN)))
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);
7178 if (ret)
7279 IWL_ERR(mld, "Failed to send MAC_CONFIG_CMD ret = %d\n", ret);
7380
7481 return ret;
7582 }
7683
77−int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif)
84+static int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif)
7885 {
7986 switch (vif->type) {
8087 case NL80211_IFTYPE_STATION:
@@ -386,7 +393,7 @@ static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy, · 305 unmodified lines
386393 iwl_mld_int_mlo_scan(mld, iwl_mld_vif_to_mac80211(mld_vif));
387394 }
388395
389−IWL_MLD_ALLOC_FN(vif, vif)
396+static IWL_MLD_ALLOC_FN(vif, vif)
390397
391398 /* Constructor function for struct iwl_mld_vif */
392399 static void
@@ -397,6 +404,7 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) · 4 unmodified lines
397404 lockdep_assert_wiphy(mld->wiphy);
398405
399406 mld_vif->mld = mld;
407+ mld_vif->fw_id = IWL_MLD_INVALID_FW_ID;
400408 mld_vif->roc_activity = ROC_NUM_ACTIVITIES;
401409
402410 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
444452
445453 lockdep_assert_wiphy(mld->wiphy);
446454
455+ /* NAN interface type is not known to FW */
456+ if (vif->type == NL80211_IFTYPE_NAN)
457+ return;
458+
447459 iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE);
448460
449461 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 @@
11 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
22 /*
3− * Copyright (C) 2024-2025 Intel Corporation
3+ * Copyright (C) 2024-2026 Intel Corporation
44 */
55 #ifndef __iwl_mld_iface_h__
66 #define __iwl_mld_iface_h__
@@ -33,6 +33,7 @@ enum iwl_mld_cca_40mhz_wa_status { · 26 unmodified lines
3333 * there is an indication that a non-BSS interface is to be added.
3434 * @IWL_MLD_EMLSR_BLOCKED_TPT: throughput is too low to make EMLSR worthwhile
3535 * @IWL_MLD_EMLSR_BLOCKED_NAN: NAN is preventing EMLSR.
36+ * @IWL_MLD_EMLSR_BLOCKED_TDLS: TDLS connection is preventing EMLSR.
3637 */
3738 enum iwl_mld_emlsr_blocked {
3839 IWL_MLD_EMLSR_BLOCKED_PREVENTION = 0x1,
@@ -42,6 +43,7 @@ enum iwl_mld_emlsr_blocked { · 3 unmodified lines
4243 IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS = 0x10,
4344 IWL_MLD_EMLSR_BLOCKED_TPT = 0x20,
4445 IWL_MLD_EMLSR_BLOCKED_NAN = 0x40,
46+ IWL_MLD_EMLSR_BLOCKED_TDLS = 0x80,
4547 };
4648
4749 /**
@@ -201,6 +203,15 @@ iwl_mld_vif_to_mac80211(struct iwl_mld_vif *mld_vif) · 153 unmodified lines
201203 return container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
202204 }
203205
206+/* Call only for interfaces that were added to the driver! */
207+static 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+
204215 #define iwl_mld_link_dereference_check(mld_vif, link_id) \
205216 rcu_dereference_check((mld_vif)->link[link_id], \
206217 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
219230 return iwl_mld_link_dereference_check(mld_vif, bss_conf->link_id);
220231 }
221232
222−int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif);
223−
224233 /* Cleanup function for struct iwl_mld_vif, will be called in restart */
225234 void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
226235 int 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
437437 iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_REMOVE);
438438 }
439439
440−IWL_MLD_ALLOC_FN(link, bss_conf)
440+static IWL_MLD_ALLOC_FN(link, bss_conf)
441441
442442 /* Constructor function for struct iwl_mld_link */
443443 static int
drivers/net/wireless/intel/iwlwifi/mld/link.h+2−0
@@ -40,6 +40,7 @@ struct iwl_probe_resp_data { · 39 unmodified lines
4040 * @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS.
4141 * @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.
4242 * @mon_sta: station used for TX injection in monitor interface.
43+ * @last_cqm_rssi_event: rssi of the last cqm rssi event
4344 * @average_beacon_energy: average beacon energy for beacons received during
4445 * client connections
4546 * @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs,
@@ -66,6 +67,7 @@ struct iwl_mld_link { · 20 unmodified lines
6667 struct iwl_mld_int_sta bcast_sta;
6768 struct iwl_mld_int_sta mcast_sta;
6869 struct iwl_mld_int_sta mon_sta;
70+ int last_cqm_rssi_event;
6971
7072 /* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */
7173 struct ieee80211_key_conf *ap_early_keys[6];
drivers/net/wireless/intel/iwlwifi/mld/low_latency.c+9−4
@@ -1,6 +1,6 @@
11 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22 /*
3− * Copyright (C) 2024-2025 Intel Corporation
3+ * Copyright (C) 2024-2026 Intel Corporation
44 */
55 #include "mld.h"
66 #include "iface.h"
@@ -77,9 +77,12 @@ static void iwl_mld_low_latency_iter(void *_data, u8 *mac, · 70 unmodified lines
7777 bool prev = mld_vif->low_latency_causes & LOW_LATENCY_TRAFFIC;
7878 bool low_latency;
7979
80− if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->low_latency.result)))
80+ if (!iwl_mld_vif_fw_id_valid(mld_vif))
8181 return;
8282
83+ BUILD_BUG_ON(ARRAY_SIZE(mld->fw_id_to_vif) !=
84+ ARRAY_SIZE(mld->low_latency.result));
85+
8386 low_latency = mld->low_latency.result[mld_vif->fw_id];
8487
8588 if (prev != low_latency)
@@ -272,8 +275,10 @@ void iwl_mld_low_latency_update_counters(struct iwl_mld *mld, · 186 unmodified lines
272275 if (WARN_ON_ONCE(!mld->low_latency.pkts_counters))
273276 return;
274277
275− if (WARN_ON_ONCE(fw_id >= ARRAY_SIZE(counters->vo_vi) ||
276− queue >= mld->trans->info.num_rxqs))
278+ if (!iwl_mld_vif_fw_id_valid(mld_vif))
279+ return;
280+
281+ if (WARN_ON_ONCE(queue >= mld->trans->info.num_rxqs))
277282 return;
278283
279284 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
754754 mld->monitor.phy.valid = false;
755755 }
756756
757+static
758+int 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+
757781 struct iwl_mld_mc_iter_data {
758782 struct iwl_mld *mld;
759783 int port_id;
@@ -1124,6 +1148,8 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw, · 364 unmodified lines
11241148
11251149 /* Now activate the link */
11261150 if (iwl_mld_can_activate_link(mld, vif, link)) {
1151+ iwl_mld_tlc_update_phy(mld, vif, link);
1152+
11271153 ret = iwl_mld_activate_link(mld, link);
11281154 if (ret)
11291155 goto err;
@@ -1185,6 +1211,8 @@ void iwl_mld_unassign_vif_chanctx(struct ieee80211_hw *hw, · 55 unmodified lines
11851211
11861212 RCU_INIT_POINTER(mld_link->chan_ctx, NULL);
11871213
1214+ iwl_mld_tlc_update_phy(mld, vif, link);
1215+
11881216 /* in the non-MLO case, remove/re-add the link to clean up FW state.
11891217 * In MLO, it'll be done in drv_change_vif_link
11901218 */
@@ -1727,14 +1755,23 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld, · 536 unmodified lines
17271755 return -EBUSY;
17281756 }
17291757
1730− ret = iwl_mld_add_sta(mld, sta, vif, STATION_TYPE_PEER);
1758+ ret = iwl_mld_add_sta(mld, sta, vif);
17311759 if (ret)
17321760 return ret;
17331761
1734− /* just added first TDLS STA, so disable PM */
1735− if (sta->tdls && tdls_count == 0)
1762+ /* just added first TDLS STA, so disable PM and block EMLSR */
1763+ if (sta->tdls && tdls_count == 0) {
17361764 iwl_mld_update_mac_power(mld, vif, false);
17371765
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+
17381775 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
17391776 mld_vif->ap_sta = sta;
17401777
@@ -1870,8 +1907,14 @@ static int iwl_mld_move_sta_state_down(struct iwl_mld *mld, · 129 unmodified lines
18701907 iwl_mld_remove_sta(mld, sta);
18711908
18721909 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+ */
18741913 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);
18751918 }
18761919 } else {
18771920 return -EINVAL;
@@ -2716,6 +2759,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = { · 838 unmodified lines
27162759 .get_antenna = iwl_mld_get_antenna,
27172760 .set_antenna = iwl_mld_set_antenna,
27182761 .add_interface = iwl_mld_mac80211_add_interface,
2762+ .change_interface = iwl_mld_mac80211_change_interface,
27192763 .remove_interface = iwl_mld_mac80211_remove_interface,
27202764 .conf_tx = iwl_mld_mac80211_conf_tx,
27212765 .prepare_multicast = iwl_mld_mac80211_prepare_multicast,
drivers/net/wireless/intel/iwlwifi/mld/mld.h+3−3
@@ -205,7 +205,7 @@ · 204 unmodified lines
205205 struct iwl_mld {
206206 /* Add here fields that need clean up on restart */
207207 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];
209209 struct ieee80211_vif __rcu *fw_id_to_vif[NUM_MAC_INDEX_DRIVER];
210210 struct ieee80211_txq __rcu *fw_id_to_txq[IWL_MAX_TVQM_QUEUES];
211211 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
530530 #define IWL_MLD_INVALID_FW_ID 0xff
531531
532532 #define IWL_MLD_ALLOC_FN(_type, _mac80211_type) \
533−static int \
533+int \
534534 iwl_mld_allocate_##_type##_fw_id(struct iwl_mld *mld, \
535− u8 *fw_id, \
535+ u8 *fw_id, \
536536 struct ieee80211_##_mac80211_type *mac80211_ptr) \
537537 { \
538538 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
1313 HOW(NON_BSS) \
1414 HOW(TMP_NON_BSS) \
1515 HOW(TPT) \
16− HOW(NAN)
16+ HOW(NAN) \
17+ HOW(TDLS)
1718
1819 static const char *
1920 iwl_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
110111 }
111112
112113 #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)
114114
115115 /* Exit reasons that can cause longer EMLSR prevention */
116116 #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
22 /*
33 * Copyright (C) 2025 Intel Corporation
44 */
5−
5+#ifndef __iwl_mld_nan_h__
6+#define __iwl_mld_nan_h__
67 #include <net/cfg80211.h>
78 #include <linux/etherdevice.h>
89
@@ -26,3 +27,5 @@ bool iwl_mld_cancel_nan_cluster_notif(struct iwl_mld *mld, · 17 unmodified lines
2627 bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld,
2728 struct iwl_rx_packet *pkt,
2829 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
3232 };
3333
3434 static inline struct iwl_mld_phy *
35−iwl_mld_phy_from_mac80211(struct ieee80211_chanctx_conf *channel)
35+iwl_mld_phy_from_mac80211(struct ieee80211_chanctx_conf *chanctx)
3636 {
37− return (void *)channel->drv_priv;
37+ return (void *)chanctx->drv_priv;
3838 }
3939
4040 /* 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
405405 .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK),
406406 .common.pwr_restriction = cpu_to_le16(u_tx_power),
407407 };
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);
409412
410413 if (WARN_ON(!mld_link))
411414 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
301301 mld->ptp_data.ptp_clock =
302302 ptp_clock_register(&mld->ptp_data.ptp_clock_info, mld->dev);
303303
304− if (IS_ERR_OR_NULL(mld->ptp_data.ptp_clock)) {
304+ if (IS_ERR(mld->ptp_data.ptp_clock)) {
305305 IWL_ERR(mld, "Failed to register PHC clock (%ld)\n",
306306 PTR_ERR(mld->ptp_data.ptp_clock));
307307 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");
308310 } else {
309311 IWL_DEBUG_INFO(mld, "Registered PHC clock: %s, with index: %d\n",
310312 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
6464 }
6565
6666 iwl_uefi_get_uats_table(mld->trans, &mld->fwrt);
67+ iwl_uefi_get_uneb_table(mld->trans, &mld->fwrt);
6768
6869 iwl_bios_get_phy_filters(&mld->fwrt);
6970 }
@@ -72,16 +73,36 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld) · 2 unmodified lines
7273 {
7374 u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD);
7475 /* 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;
7677 union iwl_geo_tx_power_profiles_cmd cmd = {
7778 .v5.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
78− .v5.table_revision = sk,
7979 };
80+ u32 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0);
81+ int n_subbands;
82+ int cmd_size;
8083 int ret;
8184
82− ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v5.table[0][0],
83− ARRAY_SIZE(cmd.v5.table[0]),
84− BIOS_GEO_MAX_PROFILE_NUM);
85+ switch (cmd_ver) {
86+ case 5:
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);
85106
86107 /* It is a valid scenario to not support SAR, or miss wgds table,
87108 * 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
89110 if (ret)
90111 return 0;
91112
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);
93114 }
94115
95116 int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
96117 {
97− u32 cmd_id = REDUCE_TX_POWER_CMD;
98118 struct iwl_dev_tx_power_cmd cmd = {
99119 .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
100− .v10.flags = cpu_to_le32(mld->fwrt.reduced_power_flags),
101120 };
121+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, REDUCE_TX_POWER_CMD, 10);
122+ int num_subbands;
123+ int cmd_size;
102124 int ret;
103125
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+
104143 /* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */
105− ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v10.per_chain[0][0][0],
106− IWL_NUM_CHAIN_TABLES, IWL_NUM_SUB_BANDS_V2,
144+ /* v10 and v11 have the same position for per_chain */
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,
107149 prof_a, prof_b);
108150 /* return on error or if the profile is disabled (positive number) */
109151 if (ret)
110152 return ret;
111153
112− return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd,
113− sizeof(cmd.common) + sizeof(cmd.v10));
154+ return iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, &cmd, cmd_size);
114155 }
115156
116157 int 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
165206 {
166207 struct iwl_fw_runtime *fwrt = &mld->fwrt;
167208 union iwl_ppag_table_cmd cmd = {
168− .v7.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,
169− .v7.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
170− .v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
209+ /* v7 and v8 have the same layout for the ppag_config_info */
210+ .v8.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,
211+ .v8.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
212+ .v8.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
171213 };
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;
172218 int ret;
173219
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+
174232 IWL_DEBUG_RADIO(fwrt,
175233 "PPAG MODE bits going to be sent: %d\n",
176234 fwrt->ppag_flags);
177235
178− for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) {
179− for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) {
180− cmd.v7.gain[chain][subband] =
181− fwrt->ppag_chains[chain].subbands[subband];
182− IWL_DEBUG_RADIO(fwrt,
183− "PPAG table: chain[%d] band[%d]: gain = %d\n",
184− chain, subband, cmd.v7.gain[chain][subband]);
236+ /* Since ver 7 will be deprecated at some point, don't bother making
237+ * this code generic for both ver 7 and ver 8: duplicate the code.
238+ */
239+ if (cmd_ver == 7) {
240+ for (int chain = 0; chain < ARRAY_SIZE(cmd.v7.gain); chain++) {
241+ for (int subband = 0;
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+ }
185269 }
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;
186285 }
187286
188287 IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
189− ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP,
190− PER_PLATFORM_ANT_GAIN_CMD),
191− &cmd, sizeof(cmd.v7));
288+ ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, cmd_len);
192289 if (ret < 0)
193290 IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
194291 ret);
@@ -352,21 +449,42 @@ void iwl_mld_configure_lari(struct iwl_mld *mld) · 157 unmodified lines
352449 ret);
353450 }
354451
355−void iwl_mld_init_uats(struct iwl_mld *mld)
452+void iwl_mld_init_ap_type_tables(struct iwl_mld *mld)
356453 {
357454 int ret;
358455 struct iwl_host_cmd cmd = {
359456 .id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
360457 MCC_ALLOWED_AP_TYPE_CMD),
361− .data[0] = &mld->fwrt.uats_table,
362− .len[0] = sizeof(mld->fwrt.uats_table),
458+ .data[0] = &mld->fwrt.ap_type_cmd,
459+ .len[0] = sizeof(mld->fwrt.ap_type_cmd),
363460 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
364461 };
365462
366− if (!mld->fwrt.uats_valid)
463+ if (!mld->fwrt.ap_type_cmd_valid)
367464 return;
368465
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+
370488 if (ret)
371489 IWL_ERR(mld, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",
372490 ret);
drivers/net/wireless/intel/iwlwifi/mld/regulatory.h+1−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
99
1010 void iwl_mld_get_bios_tables(struct iwl_mld *mld);
1111 void iwl_mld_configure_lari(struct iwl_mld *mld);
12−void iwl_mld_init_uats(struct iwl_mld *mld);
12+void iwl_mld_init_ap_type_tables(struct iwl_mld *mld);
1313 void iwl_mld_init_tas(struct iwl_mld *mld);
1414
1515 int iwl_mld_init_ppag(struct iwl_mld *mld);
drivers/net/wireless/intel/iwlwifi/mld/rx.c+14−11
@@ -1,6 +1,6 @@
11 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22 /*
3− * Copyright (C) 2024-2025 Intel Corporation
3+ * Copyright (C) 2024-2026 Intel Corporation
44 */
55
66 #include <net/mac80211.h>
@@ -791,6 +791,9 @@ static void * · 784 unmodified lines
791791 iwl_mld_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len)
792792 {
793793 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;
794797
795798 tlv = skb_put(skb, sizeof(*tlv));
796799 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
12341237
12351238 eht = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);
12361239
1237− rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
1238−
12391240 switch (u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK)) {
12401241 case 0:
12411242 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
13291330 static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld,
13301331 struct sk_buff *skb)
13311332 {
1332− struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
13331333 struct ieee80211_radiotap_vendor_content *radiotap;
13341334 const u16 vendor_data_len = sizeof(mld->monitor.cur_aid);
13351335
@@ -1353,8 +1353,6 @@ static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld, · 17 unmodified lines
13531353 /* fill the data now */
13541354 memcpy(radiotap->data, &mld->monitor.cur_aid,
13551355 sizeof(mld->monitor.cur_aid));
1356−
1357− rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
13581356 }
13591357 #endif
13601358
@@ -1362,7 +1360,6 @@ static void iwl_mld_add_rtap_sniffer_phy_data(struct iwl_mld *mld, · 1 unmodified line
13621360 struct sk_buff *skb,
13631361 struct iwl_rx_phy_air_sniffer_ntfy *ntfy)
13641362 {
1365− struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
13661363 struct ieee80211_radiotap_vendor_content *radiotap;
13671364 const u16 vendor_data_len = sizeof(*ntfy);
13681365
@@ -1382,8 +1379,6 @@ static void iwl_mld_add_rtap_sniffer_phy_data(struct iwl_mld *mld, · 13 unmodified lines
13821379
13831380 /* fill the data now */
13841381 memcpy(radiotap->data, ntfy, vendor_data_len);
1385−
1386− rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
13871382 }
13881383
13891384 static void
@@ -1407,6 +1402,7 @@ static void iwl_mld_set_rx_rate(struct iwl_mld *mld, · 17 unmodified lines
14071402 u32 rate_n_flags = phy_data->rate_n_flags;
14081403 u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);
14091404 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);
14101406 bool is_sgi = rate_n_flags & RATE_MCS_SGI_MSK;
14111407
14121408 /* 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
14811477 rx_status->encoding = RX_ENC_EHT;
14821478 iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);
14831479 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;
14841486 default:
14851487 WARN_ON_ONCE(1);
14861488 }
@@ -2204,8 +2206,9 @@ void iwl_mld_sync_rx_queues(struct iwl_mld *mld, · 717 unmodified lines
22042206 ret = wait_event_timeout(mld->rxq_sync.waitq,
22052207 READ_ONCE(mld->rxq_sync.state) == 0,
22062208 SYNC_RX_QUEUE_TIMEOUT);
2207− WARN_ONCE(!ret, "RXQ sync failed: state=0x%lx, cookie=%d\n",
2208− mld->rxq_sync.state, mld->rxq_sync.cookie);
2209+ IWL_FW_CHECK(mld, !ret,
2210+ "RXQ sync failed: state=0x%lx, cookie=%d\n",
2211+ mld->rxq_sync.state, mld->rxq_sync.cookie);
22092212
22102213 out:
22112214 mld->rxq_sync.state = 0;
drivers/net/wireless/intel/iwlwifi/mld/scan.c+169−55
@@ -47,8 +47,6 @@ · 46 unmodified lines
4747 /* adaptive dwell number of APs override mask for social channels */
4848 #define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS_BIT BIT(21)
4949
50−#define SCAN_TIMEOUT_MSEC (30000 * HZ)
51−
5250 /* minimal number of 2GHz and 5GHz channels in the regular scan request */
5351 #define IWL_MLD_6GHZ_PASSIVE_SCAN_MIN_CHANS 4
5452
@@ -116,6 +114,13 @@ struct iwl_mld_scan_params { · 61 unmodified lines
116114 u8 bssid[ETH_ALEN] __aligned(2);
117115 };
118116
117+struct 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+
119124 struct iwl_mld_scan_respect_p2p_go_iter_data {
120125 struct ieee80211_vif *current_vif;
121126 bool p2p_go;
@@ -512,9 +517,10 @@ iwl_mld_scan_get_cmd_gen_flags2(struct iwl_mld *mld, · 390 unmodified lines
512517
513518 static void
514519 iwl_mld_scan_cmd_set_dwell(struct iwl_mld *mld,
515− struct iwl_scan_general_params_v11 *gp,
516− struct iwl_mld_scan_params *params)
520+ struct iwl_mld_scan_params *params,
521+ struct iwl_scan_req_params_ptrs *scan_ptrs)
517522 {
523+ struct iwl_scan_general_params_v11 *gp = scan_ptrs->general_params;
518524 const struct iwl_mld_scan_timing_params *timing =
519525 &scan_timing[params->type];
520526
@@ -551,9 +557,10 @@ static void · 30 unmodified lines
551557 iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld,
552558 struct iwl_mld_scan_params *params,
553559 struct ieee80211_vif *vif,
554− struct iwl_scan_general_params_v11 *gp,
560+ struct iwl_scan_req_params_ptrs *scan_ptrs,
555561 enum iwl_mld_scan_status scan_status)
556562 {
563+ struct iwl_scan_general_params_v11 *gp = scan_ptrs->general_params;
557564 u16 gen_flags = iwl_mld_scan_get_cmd_gen_flags(mld, params, vif,
558565 scan_status);
559566 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
566573 gp->flags = cpu_to_le16(gen_flags);
567574 gp->flags2 = gen_flags2;
568575
569− iwl_mld_scan_cmd_set_dwell(mld, gp, params);
576+ iwl_mld_scan_cmd_set_dwell(mld, params, scan_ptrs);
570577
571578 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1)
572579 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
577584
578585 static int
579586 iwl_mld_scan_cmd_set_sched_params(struct iwl_mld_scan_params *params,
580− struct iwl_scan_umac_schedule *schedule,
581− __le16 *delay)
587+ struct iwl_scan_req_params_ptrs *scan_ptrs)
582588 {
589+ struct iwl_scan_umac_schedule *schedule =
590+ scan_ptrs->periodic_params->schedule;
591+ __le16 *delay = &scan_ptrs->periodic_params->delay;
592+
583593 if (WARN_ON(!params->n_scan_plans ||
584594 params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
585595 return -EINVAL;
@@ -657,11 +667,12 @@ iwl_mld_scan_cmd_build_ssids(struct iwl_mld_scan_params *params, · 71 unmodified lines
657667
658668 static void
659669 iwl_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)
661671 {
662672 int j, idex_s = 0, idex_b = 0;
663673 struct cfg80211_scan_6ghz_params *scan_6ghz_params =
664674 params->scan_6ghz_params;
675+ struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params;
665676
666677 for (j = 0;
667678 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
725736
726737 static void
727738 iwl_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,
729740 u32 *bitmap_ssid)
730741 {
742+ struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params;
743+
731744 pp->preq = params->preq;
732745
733746 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);
735748 return;
736749 }
737750
@@ -821,10 +834,12 @@ static u32 iwl_mld_scan_ch_n_aps_flag(enum nl80211_iftype vif_type, u8 ch_id) · 83 unmodified lines
821834 static void
822835 iwl_mld_scan_cmd_set_channels(struct iwl_mld *mld,
823836 struct ieee80211_channel **channels,
824− struct iwl_scan_channel_params_v7 *cp,
837+ struct iwl_scan_req_params_ptrs *scan_ptrs,
825838 int n_channels, u32 flags,
826839 enum nl80211_iftype vif_type)
827840 {
841+ struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params;
842+
828843 for (int i = 0; i < n_channels; i++) {
829844 enum nl80211_band band = channels[i]->band;
830845 struct iwl_scan_channel_cfg_umac *cfg = &cp->channel_config[i];
@@ -862,10 +877,11 @@ static u8 · 31 unmodified lines
862877 iwl_mld_scan_cfg_channels_6g(struct iwl_mld *mld,
863878 struct iwl_mld_scan_params *params,
864879 u32 n_channels,
865− struct iwl_scan_probe_params_v4 *pp,
866− struct iwl_scan_channel_params_v7 *cp,
880+ struct iwl_scan_req_params_ptrs *scan_ptrs,
867881 enum nl80211_iftype vif_type)
868882 {
883+ struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params;
884+ struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params;
869885 struct cfg80211_scan_6ghz_params *scan_6ghz_params =
870886 params->scan_6ghz_params;
871887 u32 i;
@@ -1063,25 +1079,23 @@ static int · 191 unmodified lines
10631079 iwl_mld_scan_cmd_set_6ghz_chan_params(struct iwl_mld *mld,
10641080 struct iwl_mld_scan_params *params,
10651081 struct ieee80211_vif *vif,
1066− struct iwl_scan_req_params_v17 *scan_p)
1082+ struct iwl_scan_req_params_ptrs *scan_ptrs)
10671083 {
1068− struct iwl_scan_channel_params_v7 *chan_p = &scan_p->channel_params;
1069− struct iwl_scan_probe_params_v4 *probe_p = &scan_p->probe_params;
1084+ struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params;
10701085
10711086 /* Explicitly clear the flags since most of them are not
10721087 * relevant for 6 GHz scan.
10731088 */
1074− chan_p->flags = 0;
1075− chan_p->count = iwl_mld_scan_cfg_channels_6g(mld, params,
1076− params->n_channels,
1077− probe_p, chan_p,
1078− vif->type);
1079− if (!chan_p->count)
1089+ cp->flags = 0;
1090+ cp->count = iwl_mld_scan_cfg_channels_6g(mld, params,
1091+ params->n_channels,
1092+ scan_ptrs, vif->type);
1093+ if (!cp->count)
10801094 return -EINVAL;
10811095
10821096 if (!params->n_ssids ||
10831097 (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;
10851099
10861100 return 0;
10871101 }
@@ -1090,12 +1104,12 @@ static int · 2 unmodified lines
10901104 iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld,
10911105 struct iwl_mld_scan_params *params,
10921106 struct ieee80211_vif *vif,
1093− struct iwl_scan_req_params_v17 *scan_p,
1107+ struct iwl_scan_req_params_ptrs *scan_ptrs,
10941108 bool low_latency,
10951109 enum iwl_mld_scan_status scan_status,
10961110 u32 channel_cfg_flags)
10971111 {
1098− struct iwl_scan_channel_params_v7 *cp = &scan_p->channel_params;
1112+ struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params;
10991113 struct ieee80211_supported_band *sband =
11001114 &mld->nvm_data->bands[NL80211_BAND_6GHZ];
11011115
@@ -1107,14 +1121,14 @@ iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld, · 5 unmodified lines
11071121
11081122 if (params->scan_6ghz)
11091123 return iwl_mld_scan_cmd_set_6ghz_chan_params(mld, params,
1110− vif, scan_p);
1124+ vif, scan_ptrs);
11111125
11121126 /* relevant only for 2.4 GHz/5 GHz scan */
11131127 cp->flags = iwl_mld_scan_cmd_set_chan_flags(mld, params, vif,
11141128 low_latency);
11151129 cp->count = params->n_channels;
11161130
1117− iwl_mld_scan_cmd_set_channels(mld, params->channels, cp,
1131+ iwl_mld_scan_cmd_set_channels(mld, params->channels, scan_ptrs,
11181132 params->n_channels, channel_cfg_flags,
11191133 vif->type);
11201134
@@ -1144,49 +1158,148 @@ iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld, · 23 unmodified lines
11441158 return 0;
11451159 }
11461160
1147−static int
1148−iwl_mld_scan_build_cmd(struct iwl_mld *mld, struct ieee80211_vif *vif,
1161+struct iwl_scan_umac_handler {
1162+ u8 version;
1163+ int (*handler)(struct iwl_mld *mld, struct ieee80211_vif *vif,
11491164 struct iwl_mld_scan_params *params,
11501165 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+
1174+static 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)
11521180 {
1153− struct iwl_scan_req_umac_v17 *cmd = mld->scan.cmd;
1154− struct iwl_scan_req_params_v17 *scan_p = &cmd->scan_params;
11551181 u32 bitmap_ssid = 0;
1156− int uid, ret;
1182+ int ret;
11571183
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);
11591186
1160− /* find a free UID entry */
1161− uid = iwl_mld_scan_uid_by_status(mld, IWL_MLD_SCAN_NONE);
1162− if (uid < 0)
1163− return uid;
1187+ ret = iwl_mld_scan_cmd_set_sched_params(params, scan_ptrs);
1188+ if (ret)
1189+ return ret;
11641190
1165− cmd->uid = cpu_to_le32(uid);
1166− cmd->ooc_priority =
1167− cpu_to_le32(iwl_mld_scan_ooc_priority(scan_status));
1191+ iwl_mld_scan_cmd_set_probe_params(params, scan_ptrs, &bitmap_ssid);
1192+
1193+ return iwl_mld_scan_cmd_set_chan_params(mld, params, vif, scan_ptrs,
1194+ low_latency, scan_status,
1195+ bitmap_ssid);
1196+}
1197+
1198+static 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;
11681211
1169− iwl_mld_scan_cmd_set_gen_params(mld, params, vif,
1170− &scan_p->general_params, scan_status);
1212+ if (WARN_ON(params->n_channels > SCAN_MAX_NUM_CHANS_V4))
1213+ return -EINVAL;
11711214
1172− ret = iwl_mld_scan_cmd_set_sched_params(params,
1173− scan_p->periodic_params.schedule,
1174− &scan_p->periodic_params.delay);
1215+ cmd->uid = cpu_to_le32(uid);
1216+ cmd->ooc_priority = cpu_to_le32(ooc_priority);
1217+
1218+ ret = iwl_mld_scan_umac_common(mld, vif, params, &scan_ptrs,
1219+ scan_status, low_latency);
11751220 if (ret)
11761221 return ret;
11771222
1178− iwl_mld_scan_cmd_set_probe_params(params, &scan_p->probe_params,
1179− &bitmap_ssid);
1223+ return uid;
1224+}
1225+
1226+static 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);
11801254
1181− ret = iwl_mld_scan_cmd_set_chan_params(mld, params, vif, scan_p,
1182− low_latency, scan_status,
1183− bitmap_ssid);
1255+ ret = iwl_mld_scan_umac_common(mld, vif, params, &scan_ptrs,
1256+ scan_status, low_latency);
11841257 if (ret)
11851258 return ret;
11861259
11871260 return uid;
11881261 }
11891262
1263+static 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+
1269+static int
1270+iwl_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+
11901303 static bool
11911304 iwl_mld_scan_pass_all(struct iwl_mld *mld,
11921305 struct cfg80211_sched_scan_request *req)
@@ -1942,9 +2055,7 @@ void iwl_mld_handle_scan_complete_notif(struct iwl_mld *mld, · 749 unmodified lines
19422055 struct ieee80211_bss_conf *link_conf = NULL;
19432056
19442057 if (fw_link_id != IWL_MLD_INVALID_FW_ID)
1945− link_conf =
1946− wiphy_dereference(mld->wiphy,
1947− mld->fw_id_to_bss_conf[fw_link_id]);
2058+ link_conf = iwl_mld_fw_id_to_link_conf(mld, fw_link_id);
19482059
19492060 /* It is possible that by the time the scan is complete the
19502061 * 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
20312142
20322143 if (scan_cmd_ver == 17) {
20332144 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);
20342147 } else {
20352148 IWL_ERR(mld, "Unexpected scan cmd version %d\n", scan_cmd_ver);
20362149 return -EINVAL;
@@ -2041,6 +2154,7 @@ int iwl_mld_alloc_scan_cmd(struct iwl_mld *mld) · 4 unmodified lines
20412154 return -ENOMEM;
20422155
20432156 mld->scan.cmd_size = scan_cmd_size;
2157+ mld->scan.cmd_ver = scan_cmd_ver;
20442158
20452159 return 0;
20462160 }
drivers/net/wireless/intel/iwlwifi/mld/scan.h+2−0
@@ -109,6 +109,7 @@ enum iwl_mld_traffic_load { · 108 unmodified lines
109109 * @traffic_load.status: The current traffic load status, see
110110 * &enum iwl_mld_traffic_load
111111 * @cmd_size: size of %cmd.
112+ * @cmd_ver: version of the scan command format.
112113 * @cmd: pointer to scan cmd buffer (allocated once in op mode start).
113114 * @last_6ghz_passive_jiffies: stores the last 6GHz passive scan time
114115 * in jiffies.
@@ -134,6 +135,7 @@ struct iwl_mld_scan { · 19 unmodified lines
134135 /* And here fields that survive a fw restart */
135136 size_t cmd_size;
136137 void *cmd;
138+ u8 cmd_ver;
137139 unsigned long last_6ghz_passive_jiffies;
138140 unsigned long last_start_time_jiffies;
139141 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
398398 return htc_flags;
399399 }
400400
401+/* Note: modifies the command depending on FW command version */
401402 static 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)
403404 {
404− int ret = iwl_mld_send_cmd_pdu(mld,
405− WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD),
406− cmd);
405+ int cmd_id = WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD);
406+ int cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0);
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);
407437 if (ret)
408438 IWL_ERR(mld, "STA_CONFIG_CMD send failed, ret=0x%x\n", ret);
409439 return ret;
@@ -431,8 +461,8 @@ iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, · 21 unmodified lines
431461 return -EINVAL;
432462
433463 cmd.sta_id = cpu_to_le32(fw_id);
464+ cmd.link_mask = cpu_to_le32(BIT(mld_link->fw_id));
434465 cmd.station_type = cpu_to_le32(mld_sta->sta_type);
435− cmd.link_id = cpu_to_le32(mld_link->fw_id);
436466
437467 memcpy(&cmd.peer_mld_address, sta->addr, ETH_ALEN);
438468 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
498528 return iwl_mld_send_sta_cmd(mld, &cmd);
499529 }
500530
501−IWL_MLD_ALLOC_FN(link_sta, link_sta)
531+static IWL_MLD_ALLOC_FN(link_sta, link_sta)
502532
503533 static int
504534 iwl_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
725755 }
726756
727757 int 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)
729759 {
730760 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
731761 struct ieee80211_link_sta *link_sta;
732762 int link_id;
733763 int ret;
734764
735− ret = iwl_mld_init_sta(mld, sta, vif, type);
765+ ret = iwl_mld_init_sta(mld, sta, vif, STATION_TYPE_PEER);
736766 if (ret)
737767 return ret;
738768
@@ -908,7 +938,7 @@ static void iwl_mld_count_mpdu(struct ieee80211_link_sta *link_sta, int queue, · 169 unmodified lines
908938 if (!(mld_vif->emlsr.blocked_reasons & IWL_MLD_EMLSR_BLOCKED_TPT))
909939 goto unlock;
910940
911− for (int i = 0; i <= IWL_FW_MAX_LINK_ID; i++)
941+ for (int i = 0; i < IWL_FW_MAX_LINKS; i++)
912942 total_mpdus += tx ? queue_counter->per_link[i].tx :
913943 queue_counter->per_link[i].rx;
914944
@@ -982,7 +1012,7 @@ iwl_mld_add_internal_sta_to_fw(struct iwl_mld *mld, · 67 unmodified lines
9821012 return iwl_mld_send_aux_sta_cmd(mld, internal_sta);
9831013
9841014 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));
9861016 cmd.station_type = cpu_to_le32(internal_sta->sta_type);
9871017
9881018 /* 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
8989 */
9090 struct iwl_mld_per_q_mpdu_counter {
9191 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];
9393 unsigned long window_start_time;
9494 } ____cacheline_aligned_in_smp;
9595
@@ -190,7 +190,7 @@ iwl_mld_link_sta_from_mac80211(struct ieee80211_link_sta *link_sta) · 94 unmodified lines
190190 }
191191
192192 int 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);
194194 void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta);
195195 int iwl_mld_fw_sta_id_from_link_sta(struct iwl_mld *mld,
196196 struct ieee80211_link_sta *link_sta);
drivers/net/wireless/intel/iwlwifi/mld/stats.c+27−4
@@ -369,15 +369,39 @@ out: · 368 unmodified lines
369369 static void iwl_mld_update_link_sig(struct ieee80211_vif *vif, int sig,
370370 struct ieee80211_bss_conf *bss_conf)
371371 {
372+ struct iwl_mld_link *link = iwl_mld_link_from_mac80211(bss_conf);
372373 struct iwl_mld *mld = iwl_mld_vif_from_mac80211(vif)->mld;
373374 int exit_emlsr_thresh;
375+ int last_event;
374376
375377 if (sig == 0) {
376378 IWL_DEBUG_RX(mld, "RSSI is 0 - skip signal based decision\n");
377379 return;
378380 }
379381
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+ }
381405
382406 if (!iwl_mld_emlsr_active(vif)) {
383407 /* 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
407431 u32 total_airtime_usec = 0;
408432
409433 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;
411435 fw_id++) {
412436 const struct iwl_stats_ntfy_per_link *link_stats;
413437 struct ieee80211_bss_conf *bss_conf;
414438 int sig;
415439
416− bss_conf = wiphy_dereference(mld->wiphy,
417− mld->fw_id_to_bss_conf[fw_id]);
440+ bss_conf = iwl_mld_fw_id_to_link_conf(mld, fw_id);
418441 if (!bss_conf || bss_conf->vif->type != NL80211_IFTYPE_STATION)
419442 continue;
420443
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
4242 iwl_construct_mld(mld, trans, cfg, fw, hw, NULL);
4343
4444 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;
4646
4747 mld->fwrt.trans = trans;
4848 mld->fwrt.fw = fw;
@@ -68,7 +68,7 @@ int iwlmld_kunit_test_init(struct kunit *test) · 19 unmodified lines
6868 return 0;
6969 }
7070
71−IWL_MLD_ALLOC_FN(link, bss_conf)
71+static IWL_MLD_ALLOC_FN(link, bss_conf)
7272
7373 static void iwlmld_kunit_init_link(struct ieee80211_vif *vif,
7474 struct ieee80211_bss_conf *link,
@@ -94,7 +94,7 @@ static void iwlmld_kunit_init_link(struct ieee80211_vif *vif, · 19 unmodified lines
9494 rcu_assign_pointer(vif->link_conf[link_id], link);
9595 }
9696
97−IWL_MLD_ALLOC_FN(vif, vif)
97+static IWL_MLD_ALLOC_FN(vif, vif)
9898
9999 /* Helper function to add and initialize a VIF for KUnit tests */
100100 struct 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
199199 vif->active_links |= BIT(link->link_id);
200200 }
201201
202−IWL_MLD_ALLOC_FN(link_sta, link_sta)
202+static IWL_MLD_ALLOC_FN(link_sta, link_sta)
203203
204204 static void iwlmld_kunit_add_link_sta(struct ieee80211_sta *sta,
205205 struct ieee80211_link_sta *link_sta,
drivers/net/wireless/intel/iwlwifi/mld/tlc.c+73−5
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include "hcmd.h"
1010 #include "sta.h"
1111 #include "phy.h"
12+#include "iface.h"
1213
1314 #include "fw/api/rs.h"
1415 #include "fw/api/context.h"
@@ -36,7 +37,8 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld, · 21 unmodified lines
3637 struct ieee80211_vif *vif,
3738 struct ieee80211_link_sta *link_sta,
3839 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)
4042 {
4143 struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
4244 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
9092 flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK;
9193 }
9294
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+
93101 return cpu_to_le16(flags);
94102 }
95103
@@ -406,6 +414,7 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif, · 310 unmodified lines
406414 struct ieee80211_supported_band *sband,
407415 const struct ieee80211_sta_he_cap *own_he_cap,
408416 const struct ieee80211_sta_eht_cap *own_eht_cap,
417+ const struct ieee80211_sta_uhr_cap *own_uhr_cap,
409418 struct iwl_tlc_config_cmd *cmd)
410419 {
411420 int i;
@@ -423,7 +432,16 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif, · 11 unmodified lines
423432 cmd->non_ht_rates = cpu_to_le16(non_ht_rates);
424433 cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
425434
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) {
427445 cmd->mode = IWL_TLC_MNG_MODE_EHT;
428446 iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap,
429447 own_eht_cap, cmd);
@@ -513,19 +531,23 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, · 83 unmodified lines
513531 struct ieee80211_bss_conf *link)
514532 {
515533 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);
516535 enum nl80211_band band = link->chanreq.oper.chan->band;
517536 struct ieee80211_supported_band *sband = mld->hw->wiphy->bands[band];
518537 const struct ieee80211_sta_he_cap *own_he_cap =
519538 ieee80211_get_he_iftype_cap_vif(sband, vif);
520539 const struct ieee80211_sta_eht_cap *own_eht_cap =
521540 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);
522543 struct iwl_tlc_config_cmd cmd = {
523544 /* For AP mode, use 20 MHz until the STA is authorized */
524545 .max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ?
525546 iwl_mld_fw_bw_from_sta_bw(link_sta) :
526547 IWL_TLC_MNG_CH_WIDTH_20MHZ,
527548 .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),
529551 .chains = iwl_mld_get_fw_chains(mld),
530552 .sgi_ch_width_supp = iwl_mld_get_fw_sgi(link_sta),
531553 .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
546568
547569 cmd.sta_mask = cpu_to_le32(BIT(fw_sta_id));
548570
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);
550575 if (WARN_ON(!chan_ctx))
551576 return;
552577
@@ -555,7 +580,7 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, · 2 unmodified lines
555580
556581 iwl_mld_fill_supp_rates(mld, vif, link_sta, sband,
557582 own_he_cap, own_eht_cap,
558− &cmd);
583+ own_uhr_cap, &cmd);
559584
560585 if (cmd_ver == 6) {
561586 cmd_ptr = &cmd;
@@ -638,6 +663,49 @@ void iwl_mld_config_tlc_link(struct iwl_mld *mld, · 76 unmodified lines
638663 iwl_mld_send_tlc_cmd(mld, vif, link_sta, link_conf);
639664 }
640665
666+void 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+
641709 void iwl_mld_config_tlc(struct iwl_mld *mld, struct ieee80211_vif *vif,
642710 struct ieee80211_sta *sta)
643711 {
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
2020
2121 int iwl_mld_send_tlc_dhc(struct iwl_mld *mld, u8 sta_id, u32 type, u32 data);
2222
23+void iwl_mld_tlc_update_phy(struct iwl_mld *mld, struct ieee80211_vif *vif,
24+ struct ieee80211_bss_conf *link_conf);
25+
2326 #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
459459
460460 static void iwl_mvm_uats_init(struct iwl_mvm *mvm)
461461 {
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 = {};
462465 u8 cmd_ver;
463466 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− };
472467
473468 if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
474469 IWL_DEBUG_RADIO(mvm, "UATS feature is not supported\n");
475470 return;
476471 }
477472
478− cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd.id,
473+ cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
479474 IWL_FW_CMD_VER_UNKNOWN);
480475 if (cmd_ver != 1) {
481476 IWL_DEBUG_RADIO(mvm,
@@ -486,10 +481,17 @@ static void iwl_mvm_uats_init(struct iwl_mvm *mvm) · 4 unmodified lines
486481
487482 iwl_uefi_get_uats_table(mvm->trans, &mvm->fwrt);
488483
489− if (!mvm->fwrt.uats_valid)
484+ if (!mvm->fwrt.ap_type_cmd_valid)
490485 return;
491486
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);
493495 if (ret < 0)
494496 IWL_ERR(mvm, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",
495497 ret);
@@ -906,7 +908,7 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) · 410 unmodified lines
906908
907909 int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
908910 {
909− union iwl_geo_tx_power_profiles_cmd geo_tx_cmd;
911+ union iwl_geo_tx_power_profiles_cmd geo_tx_cmd = {};
910912 struct iwl_geo_tx_power_profiles_resp *resp;
911913 u16 len;
912914 int ret;
@@ -958,7 +960,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) · 45 unmodified lines
958960 static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
959961 {
960962 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 = {};
962964 u16 len;
963965 u32 n_bands;
964966 u32 n_profiles;
@@ -1032,12 +1034,139 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) · 67 unmodified lines
10321034 return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);
10331035 }
10341036
1037+static 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+
1052+static 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+
10351164 int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
10361165 {
10371166 union iwl_ppag_table_cmd cmd;
10381167 int ret, cmd_size;
10391168
1040− ret = iwl_fill_ppag_table(&mvm->fwrt, &cmd, &cmd_size);
1169+ ret = iwl_mvm_fill_ppag_table(&mvm->fwrt, &cmd, &cmd_size);
10411170 /* Not supporting PPAG table is a valid scenario */
10421171 if (ret < 0)
10431172 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
62296229 ret = wait_event_timeout(mvm->rx_sync_waitq,
62306230 READ_ONCE(mvm->queue_sync_state) == 0,
62316231 SYNC_RX_QUEUE_TIMEOUT);
6232− WARN_ONCE(!ret, "queue sync: failed to sync, state is 0x%lx, cookie %d\n",
6233− mvm->queue_sync_state,
6234− mvm->queue_sync_cookie);
6232+ IWL_FW_CHECK(mvm, !ret,
6233+ "queue sync: failed to sync, state is 0x%lx, cookie %d\n",
6234+ mvm->queue_sync_state,
6235+ mvm->queue_sync_cookie);
62356236 }
62366237
62376238 out:
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
121121 int err;
122122 };
123123
124−static 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−
153−int 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−
170124 static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
171125 u32 key_flags, u32 keyidx, u32 flags)
172126 {
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c+9−9
@@ -6,7 +6,7 @@ · 5 unmodified lines
66
77 static void iwl_mvm_mld_set_he_support(struct iwl_mvm *mvm,
88 struct ieee80211_vif *vif,
9− struct iwl_mac_config_cmd *cmd,
9+ struct iwl_mac_config_cmd_v3 *cmd,
1010 int cmd_ver)
1111 {
1212 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
2424
2525 static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
2626 struct ieee80211_vif *vif,
27− struct iwl_mac_config_cmd *cmd,
27+ struct iwl_mac_config_cmd_v3 *cmd,
2828 u32 action)
2929 {
3030 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
8383 }
8484
8585 static 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)
8787 {
8888 int ret = iwl_mvm_send_cmd_pdu(mvm,
8989 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
9898 struct ieee80211_vif *vif,
9999 u32 action, bool force_assoc_off)
100100 {
101− struct iwl_mac_config_cmd cmd = {};
101+ struct iwl_mac_config_cmd_v3 cmd = {};
102102
103103 WARN_ON(vif->type != NL80211_IFTYPE_STATION);
104104
@@ -151,7 +151,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, · 46 unmodified lines
151151 struct ieee80211_vif *vif,
152152 u32 action)
153153 {
154− struct iwl_mac_config_cmd cmd = {};
154+ struct iwl_mac_config_cmd_v3 cmd = {};
155155
156156 WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
157157
@@ -170,7 +170,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm, · 12 unmodified lines
170170 struct ieee80211_vif *vif,
171171 u32 action)
172172 {
173− struct iwl_mac_config_cmd cmd = {};
173+ struct iwl_mac_config_cmd_v3 cmd = {};
174174
175175 WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
176176
@@ -187,7 +187,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm, · 10 unmodified lines
187187 struct ieee80211_vif *vif,
188188 u32 action)
189189 {
190− struct iwl_mac_config_cmd cmd = {};
190+ struct iwl_mac_config_cmd_v3 cmd = {};
191191
192192 WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
193193
@@ -210,7 +210,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_ap_go(struct iwl_mvm *mvm, · 16 unmodified lines
210210 u32 action)
211211 {
212212 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 = {};
214214
215215 WARN_ON(vif->type != NL80211_IFTYPE_AP);
216216
@@ -286,7 +286,7 @@ int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm, · 69 unmodified lines
286286 int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
287287 {
288288 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 = {
290290 .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
291291 .id_and_color = cpu_to_le32(mvmvif->id),
292292 };
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
886886 return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
887887 }
888888
889−static int
890−iwl_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−
963−out_err:
964− /* we really don't have a good way to roll back here ... */
965− mutex_unlock(&mvm->mutex);
966−
967−free:
968− for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++)
969− kfree(new_link[i]);
970− return err;
971−}
972−
973−static int
974−iwl_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−
985−static 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−
998−static enum ieee80211_neg_ttlm_res
999−iwl_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−
1016889 const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
1017890 .tx = iwl_mvm_mac_tx,
1018891 .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
1102975 .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
1103976 #endif
1104977 .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,
1110978 };
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
2020 }
2121
2222 static 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)
2424 {
2525 u32 cmd_id = WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD);
2626 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
4141 struct iwl_mvm_int_sta *sta,
4242 const u8 *addr, int link_id)
4343 {
44− struct iwl_sta_cfg_cmd cmd;
44+ struct iwl_sta_cfg_cmd_v2 cmd;
4545
4646 lockdep_assert_held(&mvm->mutex);
4747
@@ -416,7 +416,7 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta, · 368 unmodified lines
416416 struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
417417 struct iwl_mvm_vif_link_info *link_info =
418418 mvm_vif->link[link_conf->link_id];
419− struct iwl_sta_cfg_cmd cmd = {
419+ struct iwl_sta_cfg_cmd_v2 cmd = {
420420 .sta_id = cpu_to_le32(mvm_link_sta->sta_id),
421421 .station_type = cpu_to_le32(mvm_sta->sta_type),
422422 };
@@ -913,288 +913,3 @@ void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm, · 490 unmodified lines
913913
914914 rcu_read_unlock();
915915 }
916−
917−static 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−
958−static 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−
1004−static 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−
1027−int 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−
1178−err:
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
24502450 struct ieee80211_vif *vif,
24512451 struct iwl_mvm_vif_link_info *link,
24522452 unsigned int link_id);
2453−int 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);
24582453 int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
24592454 struct ieee80211_key_conf *keyconf);
24602455 u32 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
304304 IWL_ERR(mvm, "Failed to register PHC clock (%ld)\n",
305305 PTR_ERR(mvm->ptp_data.ptp_clock));
306306 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 {
308310 IWL_DEBUG_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
309311 mvm->ptp_data.ptp_clock_info.name,
310312 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
637637 struct iwl_mvm_link_sta *mvm_sta_link,
638638 unsigned int link_id);
639639 int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id);
640−int 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);
644640 u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
645641 int filter_link_id);
646642 int 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
234234 * Also convert TU to msec.
235235 */
236236 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,
238238 msecs_to_jiffies(delay));
239239
240240 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
548548 */
549549 delay = 2 * TU_TO_MS(vif->bss_conf.dtim_period *
550550 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,
552552 msecs_to_jiffies(delay));
553553 return 0;
554554 }
@@ -659,6 +659,6 @@ retry: · 104 unmodified lines
659659 /* register a timeout in case we don't succeed in switching */
660660 delay = vif->bss_conf.dtim_period * vif->bss_conf.beacon_int *
661661 1024 / 1000;
662− mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
662+ mod_delayed_work(system_percpu_wq, &mvm->tdls_cs.dwork,
663663 msecs_to_jiffies(delay));
664664 }
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
9595 CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
9696 }
9797
98−void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
98+static void
99+_iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans,
100+ bool dump_on_timeout)
99101 {
100102 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
101103 int ret;
@@ -133,7 +135,7 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans) · 31 unmodified lines
133135 "timeout waiting for FW reset ACK (inta_hw=0x%x, reset_done %d)\n",
134136 inta_hw, reset_done);
135137
136− if (!reset_done) {
138+ if (!reset_done && dump_on_timeout) {
137139 struct iwl_fw_error_dump_mode mode = {
138140 .type = IWL_ERR_TYPE_RESET_HS_TIMEOUT,
139141 .context = IWL_ERR_CONTEXT_FROM_OPMODE,
@@ -147,6 +149,11 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans) · 7 unmodified lines
147149 trans_pcie->fw_reset_state = FW_RESET_IDLE;
148150 }
149151
152+void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
153+{
154+ _iwl_trans_pcie_fw_reset_handshake(trans, false);
155+}
156+
150157 static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
151158 {
152159 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
163170 * should assume that the firmware is already dead.
164171 */
165172 trans->state = IWL_TRANS_NO_FW;
166− iwl_trans_pcie_fw_reset_handshake(trans);
173+ _iwl_trans_pcie_fw_reset_handshake(trans, true);
167174 }
168175
169176 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
31973197 if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status))
31983198 return -EINVAL;
31993199 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))
32013201 return -EINVAL;
32023202 trans->request_top_reset = 1;
32033203 }
drivers/net/wireless/mediatek/mt76/channel.c+25−14
@@ -88,6 +88,9 @@ void mt76_change_chanctx(struct ieee80211_hw *hw, · 87 unmodified lines
8888 IEEE80211_CHANCTX_CHANGE_RADAR)))
8989 return;
9090
91+ if (phy->roc_vif)
92+ mt76_abort_roc(phy);
93+
9194 cancel_delayed_work_sync(&phy->mac_work);
9295
9396 mutex_lock(&dev->mutex);
@@ -155,8 +158,6 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw, · 61 unmodified lines
155158 {
156159 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv;
157160 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;
160161 struct mt76_phy *phy = ctx->phy;
161162 struct mt76_dev *dev = phy->dev;
162163
@@ -173,15 +174,8 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw, · 10 unmodified lines
173174 if (!mlink)
174175 goto out;
175176
176− if (mlink != (struct mt76_vif_link *)vif->drv_priv)
177− rcu_assign_pointer(mvif->link[link_id], NULL);
178−
179177 dev->drv->vif_link_remove(phy, vif, link_conf, mlink);
180178 mlink->ctx = NULL;
181−
182− if (mlink != (struct mt76_vif_link *)vif->drv_priv)
183− kfree_rcu(mlink, rcu_head);
184−
185179 out:
186180 mutex_unlock(&dev->mutex);
187181 }
@@ -254,6 +248,8 @@ skip_link_replace: · 66 unmodified lines
254248 continue;
255249
256250 mlink->ctx = vifs->new_ctx;
251+ if (mlink->beacon_mon_interval)
252+ WRITE_ONCE(mlink->beacon_mon_last, jiffies);
257253 }
258254
259255 out:
@@ -324,9 +320,11 @@ void mt76_roc_complete(struct mt76_phy *phy) · 64 unmodified lines
324320
325321 if (mlink)
326322 mlink->mvif->roc_phy = NULL;
327− if (phy->main_chandef.chan &&
328− !test_bit(MT76_MCU_RESET, &dev->phy.state))
329− mt76_set_channel(phy, &phy->main_chandef, false);
323+ if (phy->chanctx && phy->main_chandef.chan && phy->offchannel &&
324+ !test_bit(MT76_MCU_RESET, &dev->phy.state)) {
325+ __mt76_set_channel(phy, &phy->main_chandef, false);
326+ mt76_offchannel_notify(phy, false);
327+ }
330328 mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link);
331329 phy->roc_vif = NULL;
332330 phy->roc_link = NULL;
@@ -364,12 +362,15 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 31 unmodified lines
364362 struct mt76_phy *phy = hw->priv;
365363 struct mt76_dev *dev = phy->dev;
366364 struct mt76_vif_link *mlink;
365+ bool offchannel;
367366 int ret = 0;
368367
369368 phy = dev->band_phys[chan->band];
370369 if (!phy)
371370 return -EINVAL;
372371
372+ cancel_delayed_work_sync(&phy->mac_work);
373+
373374 mutex_lock(&dev->mutex);
374375
375376 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
387388 mlink->mvif->roc_phy = phy;
388389 phy->roc_vif = vif;
389390 phy->roc_link = mlink;
390− cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
391− mt76_set_channel(phy, &chandef, true);
391+
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+ }
392403 ieee80211_ready_on_channel(hw);
393404 ieee80211_queue_delayed_work(phy->hw, &phy->roc_work,
394405 msecs_to_jiffies(duration));
drivers/net/wireless/mediatek/mt76/dma.c+25−8
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 #include <linux/dma-mapping.h>
77 #include "mt76.h"
88 #include "dma.h"
9+#include "mt76_connac.h"
910
1011 static struct mt76_txwi_cache *
1112 mt76_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
188189 static void
189190 mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
190191 {
191− Q_WRITE(q, desc_base, q->desc_dma);
192− if ((q->flags & MT_QFLAG_WED_RRO_EN) && !mt76_npu_device_active(dev))
192+ if ((q->flags & MT_QFLAG_WED_RRO_EN) &&
193+ (!is_mt7992(dev) || !mt76_npu_device_active(dev)))
193194 Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc);
194195 else
195196 Q_WRITE(q, ring_size, q->ndesc);
196197
197198 if (mt76_queue_is_npu_tx(q)) {
198− writel(q->desc_dma, &q->regs->desc_base);
199199 writel(q->ndesc, &q->regs->ring_size);
200+ writel(q->desc_dma, &q->regs->desc_base);
200201 }
202+
203+ Q_WRITE(q, desc_base, q->desc_dma);
201204 q->head = Q_READ(q, dma_idx);
202205 q->tail = q->head;
203206 }
@@ -663,6 +666,8 @@ mt76_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q, · 459 unmodified lines
663666 if (!t)
664667 goto free_skb;
665668
669+ t->phy_idx = phy->band_idx;
670+ t->qid = qid;
666671 txwi = mt76_get_txwi_ptr(dev, t);
667672
668673 skb->prev = skb->next = NULL;
@@ -874,7 +879,16 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) · 205 unmodified lines
874879 if (!buf)
875880 break;
876881
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))
878892 mt76_put_page_pool_buf(buf, false);
879893 } while (1);
880894
@@ -915,6 +929,13 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) · 34 unmodified lines
915929 mt76_queue_is_wed_rro(q))
916930 return;
917931
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+
918939 mt76_dma_sync_idx(dev, q);
919940 if (mt76_queue_is_npu(q))
920941 mt76_npu_fill_rx_queue(dev, q);
@@ -1168,10 +1189,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev) · 247 unmodified lines
11681189 mt76_for_each_q_rx(dev, i) {
11691190 struct mt76_queue *q = &dev->q_rx[i];
11701191
1171− if (mtk_wed_device_active(&dev->mmio.wed) &&
1172− mt76_queue_is_wed_rro(q))
1173− continue;
1174−
11751192 netif_napi_del(&dev->napi[i]);
11761193 mt76_dma_rx_cleanup(dev, q);
11771194
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
174174 static inline void
175175 mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
176176 {
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);
178180 if (mtk_wed_device_active(&dev->mmio.wed))
179181 mt76_wed_dma_setup(dev, q, true);
180182 }
drivers/net/wireless/mediatek/mt76/eeprom.c+109−45
@@ -9,6 +9,13 @@ · 8 unmodified lines
99 #include <linux/nvmem-consumer.h>
1010 #include <linux/etherdevice.h>
1111 #include "mt76.h"
12+#include "mt76_connac.h"
13+
14+enum mt76_sku_type {
15+ MT76_SKU_RATE,
16+ MT76_SKU_BACKOFF,
17+ MT76_SKU_BACKOFF_BF_OFFSET,
18+};
1219
1320 static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)
1421 {
@@ -292,7 +299,6 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) · 277 unmodified lines
292299 }
293300 EXPORT_SYMBOL_GPL(mt76_find_channel_node);
294301
295−
296302 static s8
297303 mt76_get_txs_delta(struct device_node *np, u8 nss)
298304 {
@@ -306,9 +312,24 @@ mt76_get_txs_delta(struct device_node *np, u8 nss) · 7 unmodified lines
306312 return be32_to_cpu(val[nss - 1]);
307313 }
308314
315+static 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+
309329 static void
310−mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
311− s8 target_power, s8 nss_delta, s8 *max_power)
330+mt76_apply_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
331+ const s8 *data, s8 target_power, s8 nss_delta,
332+ s8 *max_power, int n_chains, enum mt76_sku_type type)
312333 {
313334 int i;
314335
@@ -316,18 +337,51 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data, · 1 unmodified line
316337 return;
317338
318339 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+
320373 *max_power = max(*max_power, pwr[i]);
321374 }
322375 }
323376
324377 static void
325−mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
326− const s8 *data, size_t len, s8 target_power,
327− s8 nss_delta)
378+mt76_apply_multi_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
379+ s8 pwr_num, const s8 *data, size_t len,
380+ s8 target_power, s8 nss_delta, s8 *max_power,
381+ int n_chains, enum mt76_sku_type type)
328382 {
383+ static const int connac2_backoff_ru_idx = 2;
329384 int i, cur;
330− s8 max_power = -128;
331385
332386 if (!data)
333387 return;
@@ -337,8 +391,26 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, · 3 unmodified lines
337391 if (len < pwr_len + 1)
338392 break;
339393
340− mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1,
341− target_power, nss_delta, &max_power);
394+ /* Each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS
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);
342414 if (--cur > 0)
343415 continue;
344416
@@ -360,18 +432,11 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, · 15 unmodified lines
360432 struct device_node *np;
361433 const s8 *val;
362434 char name[16];
363− u32 mcs_rates = dev->drv->mcs_rates;
364− u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
365435 char band;
366436 size_t len;
367− s8 max_power = 0;
368− s8 max_power_backoff = -127;
437+ s8 max_power = -127;
369438 s8 txs_delta;
370439 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;
375440
376441 memset(dest, target_power, sizeof(*dest) - sizeof(dest->path));
377442 memset(&dest->path, 0, sizeof(dest->path));
@@ -409,46 +474,45 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, · 31 unmodified lines
409474 txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));
410475
411476 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,
413− target_power, txs_delta, &max_power);
477+ mt76_apply_array_limit(dev, dest->cck, ARRAY_SIZE(dest->cck), val,
478+ target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
414479
415− val = mt76_get_of_array_s8(np, "rates-ofdm",
416− &len, ARRAY_SIZE(dest->ofdm));
417− mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
418− target_power, txs_delta, &max_power);
480+ val = mt76_get_of_array_s8(np, "rates-ofdm", &len, ARRAY_SIZE(dest->ofdm));
481+ mt76_apply_array_limit(dev, dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
482+ target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
419483
420− val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1);
421− mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
422− ARRAY_SIZE(dest->mcs), val, len,
423− target_power, txs_delta);
484+ val = mt76_get_of_array_s8(np, "rates-mcs", &len, ARRAY_SIZE(dest->mcs[0]) + 1);
485+ mt76_apply_multi_array_limit(dev, dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
486+ ARRAY_SIZE(dest->mcs), val, len, target_power,
487+ txs_delta, &max_power, n_chains, MT76_SKU_RATE);
424488
425− val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1);
426− mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
427− ARRAY_SIZE(dest->ru), val, len,
428− target_power, txs_delta);
489+ val = mt76_get_of_array_s8(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
490+ mt76_apply_multi_array_limit(dev, dest->ru[0], ARRAY_SIZE(dest->ru[0]),
491+ ARRAY_SIZE(dest->ru), val, len, target_power,
492+ txs_delta, &max_power, n_chains, MT76_SKU_RATE);
429493
430− max_power_backoff = max_power;
431494 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,
433− target_power_combine, txs_delta, &max_power_backoff);
495+ mt76_apply_array_limit(dev, dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
496+ target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
434497
435498 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,
437− target_power_combine, txs_delta, &max_power_backoff);
499+ mt76_apply_array_limit(dev, dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
500+ target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
438501
439502 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,
441− target_power_combine, txs_delta, &max_power_backoff);
503+ mt76_apply_array_limit(dev, dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
504+ target_power, txs_delta, &max_power, n_chains,
505+ MT76_SKU_BACKOFF_BF_OFFSET);
442506
443507 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]),
445− ARRAY_SIZE(dest->path.ru), val, len,
446− target_power_combine, txs_delta);
508+ mt76_apply_multi_array_limit(dev, dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
509+ ARRAY_SIZE(dest->path.ru), val, len, target_power,
510+ txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
447511
448512 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]),
450− ARRAY_SIZE(dest->path.ru_bf), val, len,
451− target_power_combine, txs_delta);
513+ mt76_apply_multi_array_limit(dev, dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
514+ ARRAY_SIZE(dest->path.ru_bf), val, len, target_power,
515+ txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
452516
453517 return max_power;
454518 }
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
726726 INIT_LIST_HEAD(&dev->rxwi_cache);
727727 dev->token_size = dev->drv->token_size;
728728 INIT_DELAYED_WORK(&dev->scan_work, mt76_scan_work);
729+ spin_lock_init(&dev->scan_lock);
729730
730731 for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
731732 skb_queue_head_init(&dev->rx_skb[i]);
@@ -970,6 +971,9 @@ bool mt76_has_tx_pending(struct mt76_phy *phy) · 238 unmodified lines
970971 return true;
971972 }
972973
974+ if (atomic_read(&phy->mgmt_tx_pending))
975+ return true;
976+
973977 return false;
974978 }
975979 EXPORT_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
10301034 int timeout = HZ / 5;
10311035 int ret;
10321036
1033− set_bit(MT76_RESET, &phy->state);
1034−
10351037 mt76_worker_disable(&dev->tx_worker);
1038+ mt76_txq_schedule_pending(phy);
1039+
1040+ set_bit(MT76_RESET, &phy->state);
10361041 wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout);
10371042 mt76_update_survey(phy);
10381043
@@ -1716,6 +1721,16 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid) · 677 unmodified lines
17161721
17171722 idr_destroy(&wcid->pktid);
17181723
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+
17191734 spin_lock_bh(&phy->tx_lock);
17201735
17211736 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
21212136 return sel_links;
21222137 }
21232138 EXPORT_SYMBOL_GPL(mt76_select_links);
2139+
2140+struct mt76_offchannel_cb_data {
2141+ struct mt76_phy *phy;
2142+ bool offchannel;
2143+};
2144+
2145+static void
2146+mt76_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+
2187+static void
2188+mt76_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+
2227+void 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+}
2243+EXPORT_SYMBOL_GPL(mt76_offchannel_notify);
2244+
2245+struct mt76_rx_beacon_data {
2246+ struct mt76_phy *phy;
2247+ const u8 *bssid;
2248+};
2249+
2250+static 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+
2288+void 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+}
2309+EXPORT_SYMBOL_GPL(mt76_rx_beacon);
2310+
2311+static 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+
2340+void 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+}
2349+EXPORT_SYMBOL_GPL(mt76_beacon_mon_check);
drivers/net/wireless/mediatek/mt76/mcu.c+1−1
@@ -98,7 +98,7 @@ retry: · 97 unmodified lines
9898 /* orig skb might be needed for retry, mcu_skb_send_msg consumes it */
9999 if (orig_skb)
100100 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);
102102 if (ret < 0)
103103 goto out;
104104
drivers/net/wireless/mediatek/mt76/mt76.h+46−1
@@ -55,6 +55,8 @@ · 54 unmodified lines
5555 FIELD_PREP(MT_QFLAG_WED_RING, _n))
5656 #define MT_NPU_Q_TX(_n) __MT_NPU_Q(MT76_WED_Q_TX, _n)
5757 #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))
5860
5961 struct mt76_dev;
6062 struct mt76_phy;
@@ -362,6 +364,7 @@ enum mt76_wcid_flags { · 301 unmodified lines
362364 };
363365
364366 #define MT76_N_WCIDS 1088
367+#define MT76_BEACON_MON_MAX_MISS 7
365368
366369 /* stored in ieee80211_tx_info::hw_queue */
367370 #define MT_TX_HW_QUEUE_PHY GENMASK(3, 2)
@@ -448,6 +451,7 @@ struct mt76_txwi_cache { · 80 unmodified lines
448451 };
449452
450453 u8 qid;
454+ u8 phy_idx;
451455 };
452456
453457 struct mt76_rx_tid {
@@ -540,7 +544,6 @@ struct mt76_driver_ops { · 86 unmodified lines
540544 u32 survey_flags;
541545 u16 txwi_size;
542546 u16 token_size;
543− u8 mcs_rates;
544547
545548 unsigned int link_data_size;
546549
@@ -831,6 +834,8 @@ struct mt76_vif_link { · 284 unmodified lines
831834 u8 mcast_rates_idx;
832835 u8 beacon_rates_idx;
833836 bool offchannel;
837+ unsigned long beacon_mon_last;
838+ u16 beacon_mon_interval;
834839 struct ieee80211_chanctx_conf *ctx;
835840 struct mt76_wcid *wcid;
836841 struct mt76_vif_data *mvif;
@@ -859,6 +864,8 @@ struct mt76_phy { · 22 unmodified lines
859864 struct list_head tx_list;
860865 struct mt76_queue *q_tx[__MT_TXQ_MAX];
861866
867+ atomic_t mgmt_tx_pending;
868+
862869 struct cfg80211_chan_def chandef;
863870 struct cfg80211_chan_def main_chandef;
864871 bool offchannel;
@@ -1002,6 +1009,7 @@ struct mt76_dev { · 137 unmodified lines
10021009 u32 rxfilter;
10031010
10041011 struct delayed_work scan_work;
1012+ spinlock_t scan_lock;
10051013 struct {
10061014 struct cfg80211_scan_request *req;
10071015 struct ieee80211_channel *chan;
@@ -1009,6 +1017,8 @@ struct mt76_dev { · 1 unmodified line
10091017 struct mt76_vif_link *mlink;
10101018 struct mt76_phy *phy;
10111019 int chan_idx;
1020+ bool beacon_wait;
1021+ bool beacon_received;
10121022 } scan;
10131023
10141024 #ifdef CONFIG_NL80211_TESTMODE
@@ -1518,6 +1528,7 @@ void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta, · 503 unmodified lines
15181528 void mt76_tx_check_agg_ssn(struct ieee80211_sta *sta, struct sk_buff *skb);
15191529 void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid);
15201530 void mt76_txq_schedule_all(struct mt76_phy *phy);
1531+void mt76_txq_schedule_pending(struct mt76_phy *phy);
15211532 void mt76_tx_worker_run(struct mt76_dev *dev);
15221533 void mt76_tx_worker(struct mt76_worker *w);
15231534 void mt76_release_buffered_frames(struct ieee80211_hw *hw,
@@ -1596,6 +1607,9 @@ int mt76_get_rate(struct mt76_dev *dev, · 72 unmodified lines
15961607 int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
15971608 struct ieee80211_scan_request *hw_req);
15981609 void mt76_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
1610+void mt76_scan_rx_beacon(struct mt76_dev *dev, struct ieee80211_channel *chan);
1611+void mt76_rx_beacon(struct mt76_phy *phy, struct sk_buff *skb);
1612+void mt76_beacon_mon_check(struct mt76_phy *phy);
15991613 void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
16001614 const u8 *mac);
16011615 void 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
16491663 int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
16501664 struct net_device *dev, enum tc_setup_type type,
16511665 void *type_data);
1666+int 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);
16521669 #else
16531670 static inline void mt76_npu_check_ppe(struct mt76_dev *dev,
16541671 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
17071724 {
17081725 return -EOPNOTSUPP;
17091726 }
1727+
1728+static 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+}
17101734 #endif /* CONFIG_MT76_NPU */
17111735
17121736 static 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
17751799 struct mt76_queue_entry *e);
17761800 int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
17771801 bool offchannel);
1802+
1803+static inline bool
1804+mt76_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+}
17781814 int mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
17791815 bool offchannel);
17801816 void 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
17861822 struct ieee80211_vif *vif);
17871823 void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,
17881824 struct mt76_vif_link *mlink);
1825+void mt76_offchannel_notify(struct mt76_phy *phy, bool offchannel);
17891826
17901827 /* usb */
17911828 static 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
19932030 FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
19942031 }
19952032
2033+static 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+
19962041 struct mt76_txwi_cache *
19972042 mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
19982043 int 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
11671167 }
11681168 EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);
11691169
1170−void 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−}
1183−EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);
1184−
11851170 static int
11861171 mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
11871172 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
583583 }
584584 }
585585
586− if (changed & BSS_CHANGED_ERP_CTS_PROT)
587− mt7615_mac_enable_rtscts(dev, vif, info->use_cts_prot);
588−
589586 if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
590587 mt7615_mcu_add_bss_info(phy, vif, NULL, true);
591588 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
598595 BSS_CHANGED_BEACON_ENABLED))
599596 mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon);
600597
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+
601602 if (changed & BSS_CHANGED_PS)
602603 mt76_connac_mcu_set_vif_ps(&dev->mt76, vif);
603604
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
25642564 return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_ROC),
25652565 &req, sizeof(req), false);
25662566 }
2567+
2568+int 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
467467 void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy);
468468 void mt7615_mac_set_scs(struct mt7615_phy *phy, bool enable);
469469 void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy);
470−void mt7615_mac_enable_rtscts(struct mt7615_dev *dev,
471− struct ieee80211_vif *vif, bool enable);
472470 void mt7615_mac_sta_poll(struct mt7615_dev *dev);
473471 int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
474472 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
523521 int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);
524522 int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);
525523 int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);
526−
524+int mt7615_mcu_set_protection(struct mt7615_phy *phy, struct ieee80211_vif *vif,
525+ u8 ht_mode, bool use_cts_prot);
527526 int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
528527 struct ieee80211_channel *chan, int duration);
529528
drivers/net/wireless/mediatek/mt76/mt7615/regs.h+0−2
@@ -455,8 +455,6 @@ enum mt7615_reg_base { · 454 unmodified lines
455455 #define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8)
456456 #define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20)
457457
458−#define MT_WTBL_W3_RTS BIT(22)
459−
460458 #define MT_WTBL_W5_CHANGE_BW_RATE GENMASK(7, 5)
461459 #define MT_WTBL_W5_SHORT_GI_20 BIT(8)
462460 #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
182182 return mt76_chip(dev) == 0x7920;
183183 }
184184
185+static inline bool is_mt7902(struct mt76_dev *dev)
186+{
187+ return mt76_chip(dev) == 0x7902;
188+}
189+
185190 static inline bool is_mt7922(struct mt76_dev *dev)
186191 {
187192 return mt76_chip(dev) == 0x7922;
188193 }
189194
190−static inline bool is_mt7921(struct mt76_dev *dev)
195+static inline bool is_connac2(struct mt76_dev *dev)
191196 {
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);
193199 }
194200
195201 static 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
271277 case 0x7961:
272278 case 0x7920:
273279 case 0x7922:
280+ case 0x7902:
274281 case 0x7925:
275282 case 0x7663:
276283 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
173173
174174 txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
175175
176− if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))
176+ if (is_mt7663(dev) || is_connac2(dev) || is_mt7925(dev))
177177 last_mask = MT_TXD_LEN_LAST;
178178 else
179179 last_mask = MT_TXD_LEN_AMSDU_LAST |
@@ -217,7 +217,7 @@ mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev, · 37 unmodified lines
217217 u32 last_mask;
218218 int i;
219219
220− if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))
220+ if (is_mt7663(dev) || is_connac2(dev) || is_mt7925(dev))
221221 last_mask = MT_TXD_LEN_LAST;
222222 else
223223 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
309309 chandef = mvif->ctx ? &mvif->ctx->def : &mphy->chandef;
310310 band = chandef->chan->band;
311311
312− if (is_mt7921(mphy->dev)) {
312+ if (is_connac2(mphy->dev)) {
313313 rateidx = ffs(conf->basic_rates) - 1;
314314 goto legacy;
315315 }
@@ -548,7 +548,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, · 232 unmodified lines
548548 val = MT_TXD1_LONG_FORMAT |
549549 FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
550550 FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
551− if (!is_mt7921(dev))
551+ if (!is_connac2(dev))
552552 val |= MT_TXD1_VTA;
553553 if (phy_idx || band_idx)
554554 val |= MT_TXD1_TGID;
@@ -557,7 +557,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, · 2 unmodified lines
557557 txwi[2] = 0;
558558
559559 val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15);
560− if (!is_mt7921(dev))
560+ if (!is_connac2(dev))
561561 val |= MT_TXD3_SW_POWER_MGMT;
562562 if (key)
563563 val |= MT_TXD3_PROTECT_FRAME;
@@ -599,7 +599,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, · 35 unmodified lines
599599 txwi[6] |= cpu_to_le32(val);
600600 txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
601601
602− if (!is_mt7921(dev)) {
602+ if (!is_connac2(dev)) {
603603 u8 spe_idx = mt76_connac_spe_idx(mphy->antenna_mask);
604604
605605 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
831831 };
832832 struct ieee80211_radiotap_he_mu *he_mu;
833833
834− if (is_mt7921(dev)) {
834+ if (is_connac2(dev)) {
835835 mu_known.flags1 |= HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN);
836836 mu_known.flags2 |= HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN);
837837 }
@@ -1047,7 +1047,7 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, · 209 unmodified lines
10471047 stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);
10481048 gi = FIELD_GET(MT_PRXV_HT_SGI, v0);
10491049 *mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
1050− if (is_mt7921(dev))
1050+ if (is_connac2(dev))
10511051 dcm = !!(idx & MT_PRXV_TX_DCM);
10521052 else
10531053 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
11531153 return;
11541154
11551155 wcid = (struct mt76_wcid *)sta->drv_priv;
1156− if (!test_and_set_bit(tid, &wcid->ampdu_state))
1157− ieee80211_start_tx_ba_session(sta, tid, 0);
1156+ if (!test_and_set_bit(tid, &wcid->ampdu_state)) {
1157+ if (ieee80211_start_tx_ba_session(sta, tid, 0))
1158+ clear_bit(tid, &wcid->ampdu_state);
1159+ }
11581160 }
11591161 EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr);
11601162
@@ -1207,5 +1209,11 @@ void mt76_connac2_tx_token_put(struct mt76_dev *dev) · 46 unmodified lines
12071209 }
12081210 spin_unlock_bh(&dev->token_lock);
12091211 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+ }
12101218 }
12111219 EXPORT_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
44 #include <linux/firmware.h>
55 #include "mt76_connac2_mac.h"
66 #include "mt76_connac_mcu.h"
7+#include "mt792x_regs.h"
78
89 int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
910 {
@@ -65,7 +66,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len, · 55 unmodified lines
6566 int cmd;
6667
6768 if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
68− (is_mt7921(dev) && addr == 0x900000) ||
69+ (is_connac2(dev) && addr == 0x900000) ||
6970 (is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
7071 (is_mt799x(dev) && addr == 0x900000))
7172 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
402403 switch (vif->type) {
403404 case NL80211_IFTYPE_MESH_POINT:
404405 case NL80211_IFTYPE_AP:
405− if (vif->p2p && !is_mt7921(dev))
406+ if (vif->p2p && !is_connac2(dev))
406407 conn_type = CONNECTION_P2P_GC;
407408 else
408409 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
410411 basic->aid = cpu_to_le16(link_sta->sta->aid);
411412 break;
412413 case NL80211_IFTYPE_STATION:
413− if (vif->p2p && !is_mt7921(dev))
414+ if (vif->p2p && !is_connac2(dev))
414415 conn_type = CONNECTION_P2P_GO;
415416 else
416417 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
874875 struct sta_rec_vht *vht;
875876 int len;
876877
877− len = is_mt7921(dev) ? sizeof(*vht) : sizeof(*vht) - 4;
878+ len = is_connac2(dev) ? sizeof(*vht) : sizeof(*vht) - 4;
878879 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, len);
879880 vht = (struct sta_rec_vht *)tlv;
880881 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
885886 /* starec uapsd */
886887 mt76_connac_mcu_sta_uapsd(skb, vif, sta);
887888
888− if (!is_mt7921(dev))
889+ if (!is_connac2(dev))
889890 return;
890891
891892 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
12951296 wtbl_hdr);
12961297
12971298 ret = mt76_connac_mcu_sta_wed_update(dev, skb);
1298− if (ret)
1299+ if (ret) {
1300+ dev_kfree_skb(skb);
12991301 return ret;
1302+ }
13001303
13011304 ret = mt76_mcu_skb_send_msg(dev, skb, cmd, true);
13021305 if (ret)
@@ -1309,8 +1312,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, · 6 unmodified lines
13091312 mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);
13101313
13111314 ret = mt76_connac_mcu_sta_wed_update(dev, skb);
1312− if (ret)
1315+ if (ret) {
1316+ dev_kfree_skb(skb);
13131317 return ret;
1318+ }
13141319
13151320 return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
13161321 }
@@ -1774,7 +1779,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, · 457 unmodified lines
17741779 req->ssid_type_ext = n_ssids ? BIT(0) : 0;
17751780 req->ssids_num = n_ssids;
17761781
1777− duration = is_mt7921(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;
1782+ duration = is_connac2(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;
17781783 /* increase channel time for passive scan */
17791784 if (!sreq->n_ssids)
17801785 duration *= 2;
@@ -1817,7 +1822,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, · 36 unmodified lines
18171822 req->ies_len = cpu_to_le16(sreq->ie_len);
18181823 }
18191824
1820− if (is_mt7921(phy->dev))
1825+ if (is_connac2(phy->dev))
18211826 req->scan_func |= SCAN_FUNC_SPLIT_SCAN;
18221827
18231828 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
18931898 get_random_mask_addr(addr, sreq->mac_addr,
18941899 sreq->mac_addr_mask);
18951900 }
1896− if (is_mt7921(phy->dev)) {
1901+ if (is_connac2(phy->dev)) {
18971902 req->mt7921.bss_idx = mvif->idx;
18981903 req->mt7921.delay = cpu_to_le32(sreq->delay);
18991904 }
@@ -2033,7 +2038,7 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku, · 133 unmodified lines
20332038 struct mt76_power_limits *limits,
20342039 enum nl80211_band band)
20352040 {
2036− int max_power = is_mt7921(dev) ? 127 : 63;
2041+ int max_power = is_connac2(dev) ? 127 : 63;
20372042 int i, offset = sizeof(limits->cck);
20382043
20392044 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
20612066 offset += 12;
20622067 }
20632068
2064− if (!is_mt7921(dev))
2069+ if (!is_connac2(dev))
20652070 return;
20662071
20672072 /* he */
@@ -2117,7 +2122,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, · 49 unmodified lines
21172122 enum nl80211_band band)
21182123 {
21192124 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;
21212126 static const u8 chan_list_2ghz[] = {
21222127 1, 2, 3, 4, 5, 6, 7,
21232128 8, 9, 10, 11, 12, 13, 14
@@ -2158,7 +2163,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, · 34 unmodified lines
21582163 if (!limits)
21592164 return -ENOMEM;
21602165
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;
21622167 tx_power = 2 * phy->hw->conf.power_level;
21632168 if (!tx_power)
21642169 tx_power = 127;
@@ -2242,6 +2247,9 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, · 77 unmodified lines
22422247 false);
22432248 if (err < 0)
22442249 goto out;
2250+
2251+ /* read a CR to avoid PSE buffer underflow */
2252+ mt76_connac_mcu_reg_rr(dev, MT_PSE_BASE);
22452253 }
22462254
22472255 out:
@@ -2764,12 +2772,16 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, · 516 unmodified lines
27642772 return PTR_ERR(skb);
27652773
27662774 ret = mt76_connac_mcu_sta_key_tlv(sta_key_conf, skb, key, cmd);
2767− if (ret)
2775+ if (ret) {
2776+ dev_kfree_skb(skb);
27682777 return ret;
2778+ }
27692779
27702780 ret = mt76_connac_mcu_sta_wed_update(dev, skb);
2771− if (ret)
2781+ if (ret) {
2782+ dev_kfree_skb(skb);
27722783 return ret;
2784+ }
27732785
27742786 return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
27752787 }
@@ -3072,7 +3084,7 @@ static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info) · 296 unmodified lines
30723084 {
30733085 u32 mode = DL_MODE_NEED_RSP;
30743086
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)
30763088 return mode;
30773089
30783090 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
628628 __le32 flag;
629629 } __packed;
630630
631+struct sta_rec_eml_op {
632+ __le16 tag;
633+ __le16 len;
634+ u8 link_bitmap;
635+ u8 link_ant_num[3];
636+} __packed;
637+
631638 /* wtbl_rec */
632639
633640 struct wtbl_req_hdr {
@@ -796,6 +803,7 @@ struct wtbl_raw { · 162 unmodified lines
796803 sizeof(struct sta_rec_he_6g_capa) + \
797804 sizeof(struct sta_rec_pn_info) + \
798805 sizeof(struct sta_rec_tx_proc) + \
806+ sizeof(struct sta_rec_eml_op) + \
799807 sizeof(struct tlv) + \
800808 MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
801809
@@ -832,6 +840,7 @@ enum { · 30 unmodified lines
832840 STA_REC_PN_INFO = 0x26,
833841 STA_REC_KEY_V3 = 0x27,
834842 STA_REC_HDRT = 0x28,
843+ STA_REC_EML_OP = 0x29,
835844 STA_REC_HDR_TRANS = 0x2B,
836845 STA_REC_MAX_NUM
837846 };
@@ -1308,7 +1317,9 @@ enum { · 470 unmodified lines
13081317 MCU_UNI_CMD_PER_STA_INFO = 0x6d,
13091318 MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
13101319 MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
1320+ MCU_UNI_CMD_EXT_EEPROM_CTRL = 0x74,
13111321 MCU_UNI_CMD_RADIO_STATUS = 0x80,
1322+ MCU_UNI_CMD_MLD = 0x82,
13121323 MCU_UNI_CMD_SDO = 0x88,
13131324 };
13141325
@@ -1363,6 +1374,7 @@ enum { · 48 unmodified lines
13631374 UNI_BSS_INFO_BASIC = 0,
13641375 UNI_BSS_INFO_RA = 1,
13651376 UNI_BSS_INFO_RLM = 2,
1377+ UNI_BSS_INFO_PROTECT_INFO = 3,
13661378 UNI_BSS_INFO_BSS_COLOR = 4,
13671379 UNI_BSS_INFO_HE_BASIC = 5,
13681380 UNI_BSS_INFO_11V_MBSSID = 6,
@@ -1383,6 +1395,7 @@ enum { · 14 unmodified lines
13831395 UNI_BSS_INFO_MLD = 26,
13841396 UNI_BSS_INFO_PM_DISABLE = 27,
13851397 UNI_BSS_INFO_EHT = 30,
1398+ UNI_BSS_INFO_MLD_LINK_OP = 36,
13861399 };
13871400
13881401 enum {
@@ -1865,7 +1878,7 @@ mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa) · 476 unmodified lines
18651878
18661879 ret |= feature_set & FW_FEATURE_SET_ENCRYPT ?
18671880 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))
18691882 ret |= feature_set & FW_FEATURE_ENCRY_MODE ?
18701883 DL_CONFIG_ENCRY_MODE_SEL : 0;
18711884 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
534534 return;
535535
536536 clear_bit(MT76_RESTART, &dev->mphy.state);
537+ ieee80211_wake_queues(hw);
537538 }
538539 EXPORT_SYMBOL_GPL(mt76x02_reconfig_complete);
539540
drivers/net/wireless/mediatek/mt76/mt7915/init.c+1−0
@@ -1294,6 +1294,7 @@ free_phy2: · 1293 unmodified lines
12941294
12951295 void mt7915_unregister_device(struct mt7915_dev *dev)
12961296 {
1297+ cancel_work_sync(&dev->dump_work);
12971298 mt7915_unregister_ext_phy(dev);
12981299 mt7915_coredump_unregister(dev);
12991300 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
232232 rcu_read_unlock();
233233 }
234234
235−void 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−
248235 static void
249236 mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q,
250237 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
6868 if (ret)
6969 goto out;
7070
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,
7272 phy->mt76->band_idx);
7373 if (ret)
7474 goto out;
@@ -633,8 +633,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, · 558 unmodified lines
633633 if (set_sta == 1)
634634 mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);
635635
636− if (changed & BSS_CHANGED_ERP_CTS_PROT)
637− mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);
636+ if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
637+ mt7915_mcu_set_protection(phy, vif, info->ht_operation_mode,
638+ info->use_cts_prot);
638639
639640 if (changed & BSS_CHANGED_ERP_SLOT) {
640641 int slottime = 9;
@@ -851,8 +852,10 @@ int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, · 210 unmodified lines
851852 return mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_PORT_SECURE, false);
852853
853854 case MT76_STA_EVENT_DISASSOC:
855+ mutex_lock(&dev->mt76.mutex);
854856 for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
855857 mt7915_mac_twt_teardown_flow(dev, msta, i);
858+ mutex_unlock(&dev->mt76.mutex);
856859
857860 mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false);
858861 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
17651765 }
17661766 out:
17671767 ret = mt76_connac_mcu_sta_wed_update(&dev->mt76, skb);
1768− if (ret)
1768+ if (ret) {
1769+ dev_kfree_skb(skb);
17691770 return ret;
1771+ }
17701772
17711773 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
17721774 MCU_EXT_CMD(STA_REC_UPDATE), true);
@@ -3954,6 +3956,68 @@ out: · 2181 unmodified lines
39543956 return ret;
39553957 }
39563958
3959+int 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+
39574021 int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
39584022 struct cfg80211_he_bss_color *he_bss_color)
39594023 {
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h+11−0
@@ -399,6 +399,17 @@ struct bss_info_inband_discovery { · 398 unmodified lines
399399 __le16 prob_rsp_len;
400400 } __packed __aligned(4);
401401
402+struct 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+
402413 enum {
403414 BSS_INFO_BCN_CSA,
404415 BSS_INFO_BCN_BCC,
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h+4−0
@@ -84,6 +84,8 @@ · 83 unmodified lines
8484 #define MT7915_CRIT_TEMP 110
8585 #define MT7915_MAX_TEMP 120
8686
87+#define MT7915_RTS_LEN_THRES 0x92b
88+
8789 struct mt7915_vif;
8890 struct mt7915_sta;
8991 struct mt7915_dfs_pulse;
@@ -473,6 +475,8 @@ int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *v · 383 unmodified lines
473475 u32 changed);
474476 int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
475477 int enable, u32 changed);
478+int mt7915_mcu_set_protection(struct mt7915_phy *phy, struct ieee80211_vif *vif,
479+ u8 ht_mode, bool use_cts_prot);
476480 int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,
477481 struct ieee80211_he_obss_pd *he_obss_pd);
478482 int 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
302302 dev->pm.idle_timeout = MT792x_PM_TIMEOUT;
303303 dev->pm.stats.last_wake_event = jiffies;
304304 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)) {
306308 dev->pm.enable_user = true;
307309 dev->pm.enable = true;
308310 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
371371 {
372372 struct mt792x_phy *phy = &dev->phy;
373373
374+ if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
375+ return;
376+
374377 timer_delete_sync(&phy->roc_timer);
375− cancel_work_sync(&phy->roc_work);
376− if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
377− ieee80211_iterate_interfaces(mt76_hw(dev),
378− IEEE80211_IFACE_ITER_RESUME_ALL,
379− mt7921_roc_iter, (void *)phy);
378+ cancel_work(&phy->roc_work);
379+
380+ ieee80211_iterate_interfaces(mt76_hw(dev),
381+ IEEE80211_IFACE_ITER_RESUME_ALL,
382+ mt7921_roc_iter, (void *)phy);
380383 }
381384 EXPORT_SYMBOL_GPL(mt7921_roc_abort_sync);
382385
@@ -387,10 +390,11 @@ void mt7921_roc_work(struct work_struct *work) · 4 unmodified lines
387390 phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,
388391 roc_work);
389392
390− if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
391− return;
392−
393393 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+ }
394398 ieee80211_iterate_active_interfaces(phy->mt76->hw,
395399 IEEE80211_IFACE_ITER_RESUME_ALL,
396400 mt7921_roc_iter, phy);
@@ -796,7 +800,8 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add) · 399 unmodified lines
796800 }
797801
798802 out:
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);
800805 }
801806
802807 int 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
807812 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
808813 int ret, idx;
809814
815+ if (sta->aid > MT7921_MAX_AID)
816+ return -ENOENT;
817+
810818 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);
811819 if (idx < 0)
812820 return -ENOSPC;
@@ -850,6 +858,9 @@ int mt7921_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, · 37 unmodified lines
850858 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
851859 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
852860
861+ if (sta->aid > MT7921_MAX_AID)
862+ return -ENOENT;
863+
853864 if (ev != MT76_STA_EVENT_ASSOC)
854865 return 0;
855866
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
13531353 u16 len = le16_to_cpu(rule->len);
13541354 u16 offset = len + sizeof(*rule);
13551355
1356+ if (buf_len < offset)
1357+ break;
1358+
13561359 pos += offset;
13571360 buf_len -= offset;
13581361 if (rule->alpha2[0] != alpha2[0] ||
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h+16−0
@@ -7,6 +7,8 @@ · 6 unmodified lines
77 #include "../mt792x.h"
88 #include "regs.h"
99
10+#define MT7921_MAX_AID 20
11+
1012 #define MT7921_TX_RING_SIZE 2048
1113 #define MT7921_TX_MCU_RING_SIZE 256
1214 #define MT7921_TX_FWDL_RING_SIZE 128
@@ -15,6 +17,9 @@ · 2 unmodified lines
1517 #define MT7921_RX_MCU_RING_SIZE 8
1618 #define MT7921_RX_MCU_WA_RING_SIZE 512
1719
20+/* MT7902 Rx Ring0 is for both Rx Event and Tx Done Event */
21+#define MT7902_RX_MCU_RING_SIZE 512
22+
1823 #define MT7921_EEPROM_SIZE 3584
1924 #define MT7921_TOKEN_SIZE 8192
2025
@@ -117,6 +122,17 @@ enum mt7921_rxq_id { · 96 unmodified lines
117122 MT7921_RXQ_MCU_WM = 0,
118123 };
119124
125+/* MT7902 assigns its MCU-WM TXQ at index 15 */
126+enum mt7902_txq_id {
127+ MT7902_TXQ_MCU_WM = 15,
128+};
129+
130+struct mt7921_dma_layout {
131+ u8 mcu_wm_txq;
132+ u16 mcu_rxdone_ring_size;
133+ bool has_mcu_wa;
134+};
135+
120136 enum {
121137 MT7921_CLC_POWER,
122138 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
2626 .driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
2727 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7920),
2828 .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 },
2931 { },
3032 };
3133
@@ -167,8 +169,29 @@ static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) · 135 unmodified lines
167169
168170 static int mt7921_dma_init(struct mt792x_dev *dev)
169171 {
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;
170179 int ret;
171180
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+
172195 mt76_dma_attach(&dev->mt76);
173196
174197 ret = mt792x_dma_disable(dev, true);
@@ -185,7 +208,7 @@ static int mt7921_dma_init(struct mt792x_dev *dev) · 10 unmodified lines
185208 mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
186209
187210 /* 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,
189212 MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
190213 if (ret)
191214 return ret;
@@ -199,18 +222,20 @@ static int mt7921_dma_init(struct mt792x_dev *dev) · 7 unmodified lines
199222 /* event from WM before firmware download */
200223 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
201224 MT7921_RXQ_MCU_WM,
202− MT7921_RX_MCU_RING_SIZE,
225+ layout.mcu_rxdone_ring_size,
203226 MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
204227 if (ret)
205228 return ret;
206229
207− /* Change mcu queue after firmware download */
208− ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
209− MT7921_RXQ_MCU_WM,
210− MT7921_RX_MCU_WA_RING_SIZE,
211− MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
212− if (ret)
213− return ret;
230+ if (layout.has_mcu_wa) {
231+ /* Change mcu queue after firmware download */
232+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
233+ MT7921_RXQ_MCU_WM,
234+ MT7921_RX_MCU_WA_RING_SIZE,
235+ MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
236+ if (ret)
237+ return ret;
238+ }
214239
215240 /* rx data */
216241 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
276301 struct mt76_bus_ops *bus_ops;
277302 struct mt792x_dev *dev;
278303 struct mt76_dev *mdev;
304+ void __iomem *regs;
279305 u16 cmd, chipid;
280306 u8 features;
281307 int ret;
@@ -284,10 +310,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev, · 2 unmodified lines
284310 if (ret)
285311 return ret;
286312
287− ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
288− if (ret)
289− return ret;
290−
291313 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
292314 if (!(cmd & PCI_COMMAND_MEMORY)) {
293315 cmd |= PCI_COMMAND_MEMORY;
@@ -321,11 +343,29 @@ static int mt7921_pci_probe(struct pci_dev *pdev, · 27 unmodified lines
321343
322344 pci_set_drvdata(pdev, mdev);
323345
346+ regs = pcim_iomap_region(pdev, 0, pci_name(pdev));
347+ if (IS_ERR(regs))
348+ return PTR_ERR(regs);
349+
324350 dev = container_of(mdev, struct mt792x_dev, mt76);
325351 dev->fw_features = features;
326352 dev->hif_ops = &mt7921_pcie_ops;
327353 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+
329369 tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
330370
331371 dev->phy.dev = dev;
@@ -579,6 +619,8 @@ MODULE_FIRMWARE(MT7921_FIRMWARE_WM); · 247 unmodified lines
579619 MODULE_FIRMWARE(MT7921_ROM_PATCH);
580620 MODULE_FIRMWARE(MT7922_FIRMWARE_WM);
581621 MODULE_FIRMWARE(MT7922_ROM_PATCH);
622+MODULE_FIRMWARE(MT7902_FIRMWARE_WM);
623+MODULE_FIRMWARE(MT7902_ROM_PATCH);
582624 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
583625 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
584626 MODULE_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
7171 mt76_txq_schedule_all(&dev->mphy);
7272
7373 mt76_worker_disable(&dev->mt76.tx_worker);
74− napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]);
75− napi_disable(&dev->mt76.napi[MT_RXQ_MCU]);
76− napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
74+ mt76_for_each_q_rx(&dev->mt76, i) {
75+ napi_disable(&dev->mt76.napi[i]);
76+ }
7777 napi_disable(&dev->mt76.tx_napi);
7878
7979 mt76_connac2_tx_token_put(&dev->mt76);
drivers/net/wireless/mediatek/mt76/mt7921/sdio.c+4−0
@@ -19,6 +19,8 @@ · 18 unmodified lines
1919 static const struct sdio_device_id mt7921s_table[] = {
2020 { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7901),
2121 .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 },
2224 { } /* Terminating entry */
2325 };
2426
@@ -317,6 +319,8 @@ failed: · 292 unmodified lines
317319 MODULE_DEVICE_TABLE(sdio, mt7921s_table);
318320 MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
319321 MODULE_FIRMWARE(MT7921_ROM_PATCH);
322+MODULE_FIRMWARE(MT7902_FIRMWARE_WM);
323+MODULE_FIRMWARE(MT7902_ROM_PATCH);
320324
321325 static DEFINE_SIMPLE_DEV_PM_OPS(mt7921s_pm_ops, mt7921s_suspend, mt7921s_resume);
322326
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
9191
9292 mt7925_mac_init_basic_rates(dev);
9393
94+ memzero_explicit(&dev->mt76.alpha2, sizeof(dev->mt76.alpha2));
95+
9496 return 0;
9597 }
9698 EXPORT_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
804804 txwi[5] = cpu_to_le32(val);
805805
806806 val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
807− if (!ieee80211_vif_is_mld(vif) ||
808− (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0))
807+ if (vif && (!ieee80211_vif_is_mld(vif) ||
808+ (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)))
809809 val |= MT_TXD6_DIS_MAT;
810810 txwi[6] = cpu_to_le32(val);
811811 txwi[7] = 0;
@@ -846,11 +846,14 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb, · 34 unmodified lines
846846 bool is_8023;
847847 u16 fc, tid;
848848
849+ if (!sta)
850+ return;
851+
849852 link_sta = rcu_dereference(sta->link[wcid->link_id]);
850853 if (!link_sta)
851854 return;
852855
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))
854857 return;
855858
856859 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
882885 else
883886 mlink = &msta->deflink;
884887
885− if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state))
886− ieee80211_start_tx_ba_session(sta, tid, 0);
888+ if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state)) {
889+ if (ieee80211_start_tx_ba_session(sta, tid, 0))
890+ clear_bit(tid, &mlink->wcid.ampdu_state);
891+ }
887892 }
888893
889894 static bool
@@ -1280,7 +1285,8 @@ mt7925_vif_connect_iter(void *priv, u8 *mac, · 390 unmodified lines
12801285 if (vif->type == NL80211_IFTYPE_AP) {
12811286 mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.deflink.wcid,
12821287 true, NULL);
1283− mt7925_mcu_sta_update(dev, NULL, vif, true,
1288+ mt7925_mcu_sta_update(dev, NULL, vif,
1289+ &mvif->sta.deflink, true,
12841290 MT76_STA_INFO_STATE_NONE);
12851291 mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true);
12861292 }
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
245245 {
246246 struct wiphy *wiphy = phy->mt76->hw->wiphy;
247247 static const u8 ext_capa_sta[] = {
248+ [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
248249 [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
249250 [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
250251 };
@@ -438,6 +439,9 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) · 187 unmodified lines
438439 if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN)
439440 vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI;
440441
442+ INIT_WORK(&mvif->csa_work, mt7925_csa_work);
443+ timer_setup(&mvif->csa_timer, mt792x_csa_timer, 0);
444+
441445 out:
442446 mt792x_mutex_release(dev);
443447
@@ -457,12 +461,16 @@ void mt7925_roc_abort_sync(struct mt792x_dev *dev) · 13 unmodified lines
457461 {
458462 struct mt792x_phy *phy = &dev->phy;
459463
464+ if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
465+ return;
466+
460467 timer_delete_sync(&phy->roc_timer);
461− cancel_work_sync(&phy->roc_work);
462− if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
463− ieee80211_iterate_interfaces(mt76_hw(dev),
464− IEEE80211_IFACE_ITER_RESUME_ALL,
465− mt7925_roc_iter, (void *)phy);
468+
469+ cancel_work(&phy->roc_work);
470+
471+ ieee80211_iterate_interfaces(mt76_hw(dev),
472+ IEEE80211_IFACE_ITER_RESUME_ALL,
473+ mt7925_roc_iter, (void *)phy);
466474 }
467475 EXPORT_SYMBOL_GPL(mt7925_roc_abort_sync);
468476
@@ -541,7 +549,7 @@ static int mt7925_set_mlo_roc(struct mt792x_phy *phy, · 72 unmodified lines
541549
542550 phy->roc_grant = false;
543551
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);
545553 if (err < 0) {
546554 clear_bit(MT76_STATE_ROC, &phy->mt76->state);
547555 goto out;
@@ -586,7 +594,8 @@ static int mt7925_cancel_remain_on_channel(struct ieee80211_hw *hw, · 38 unmodified lines
586594
587595 static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
588596 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)
590599 {
591600 struct mt792x_dev *dev = mt792x_hw_dev(hw);
592601 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
595604 struct ieee80211_bss_conf *link_conf;
596605 struct ieee80211_link_sta *link_sta;
597606 int idx = key->keyidx, err = 0;
598− struct mt792x_link_sta *mlink;
599607 struct mt792x_bss_conf *mconf;
600608 struct mt76_wcid *wcid;
601609 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
603611 link_conf = mt792x_vif_to_bss_conf(vif, link_id);
604612 link_sta = sta ? mt792x_sta_to_link_sta(vif, sta, link_id) : NULL;
605613 mconf = mt792x_vif_to_link(mvif, link_id);
606− mlink = mt792x_sta_to_link(msta, link_id);
607614 wcid = &mlink->wcid;
608615 wcid_keyidx = &wcid->hw_key_idx;
609616
@@ -671,6 +678,7 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, · 61 unmodified lines
671678 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
672679 struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv :
673680 &mvif->sta;
681+ struct mt792x_link_sta *mlink;
674682 int err;
675683
676684 /* 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
692700 add = key->link_id != -1 ? BIT(key->link_id) : msta->valid_links;
693701
694702 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);
696706 if (err < 0)
697707 break;
698708 }
699709 } 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);
701713 }
702714
703715 mt792x_mutex_release(dev);
@@ -842,20 +854,24 @@ mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 138 unmodified lines
842854
843855 static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
844856 struct ieee80211_vif *vif,
845− struct ieee80211_link_sta *link_sta)
857+ struct ieee80211_link_sta *link_sta,
858+ struct mt792x_link_sta *mlink)
846859 {
847860 struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
848861 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
849862 struct ieee80211_bss_conf *link_conf;
850863 struct mt792x_bss_conf *mconf;
851864 u8 link_id = link_sta->link_id;
852− struct mt792x_link_sta *mlink;
865+ bool wcid_published = false;
853866 struct mt792x_sta *msta;
854867 struct mt76_wcid *wcid;
868+ bool pm_woken = false;
855869 int ret, idx;
856870
857871 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;
859875
860876 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);
861877 if (idx < 0)
@@ -874,14 +890,15 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, · 12 unmodified lines
874890 wcid = &mlink->wcid;
875891 ewma_signal_init(&wcid->rssi);
876892 rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid);
877− mt76_wcid_init(wcid, 0);
893+ wcid_published = true;
878894 ewma_avg_signal_init(&mlink->avg_ack_signal);
879895 memset(mlink->airtime_ac, 0,
880896 sizeof(msta->deflink.airtime_ac));
881897
882898 ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
883899 if (ret)
884− return ret;
900+ goto out_wcid;
901+ pm_woken = true;
885902
886903 mt7925_mac_wtbl_update(dev, idx,
887904 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -890,41 +907,125 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, · 2 unmodified lines
890907
891908 /* should update bss info before STA add */
892909 if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) {
893− if (ieee80211_vif_is_mld(vif))
894− mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,
895− link_conf, link_sta, link_sta != mlink->pri_link);
896− else
897− mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,
898− link_conf, link_sta, false);
910+ struct mt792x_link_sta *mlink_bc;
911+
912+ mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
913+
914+ if (ieee80211_vif_is_mld(vif)) {
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+ }
899929 }
900930
901931 if (ieee80211_vif_is_mld(vif) &&
902932 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,
904935 MT76_STA_INFO_STATE_NONE);
905936 if (ret)
906− return ret;
937+ goto out_pm;
907938 } else if (ieee80211_vif_is_mld(vif) &&
908939 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+
909955 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);
911958 if (ret)
912− return ret;
959+ goto out_pm;
913960
914− ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,
961+ ret = mt7925_mcu_sta_update(dev, link_sta, vif,
962+ mlink, true,
915963 MT76_STA_INFO_STATE_ASSOC);
916964 if (ret)
917− return ret;
965+ goto out_pm;
918966 } 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,
920969 MT76_STA_INFO_STATE_NONE);
921970 if (ret)
922− return ret;
971+ goto out_pm;
923972 }
924973
925974 mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
926975
927976 return 0;
977+
978+out_pm:
979+ if (pm_woken)
980+ mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
981+out_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+ */
1000+static void
1001+mt7925_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+ }
9281029 }
9291030
9301031 static int
@@ -932,34 +1033,50 @@ mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, · 1 unmodified line
9321033 struct ieee80211_sta *sta, unsigned long new_links)
9331034 {
9341035 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
1036+ unsigned long added_links = 0;
9351037 unsigned int link_id;
9361038 int err = 0;
9371039
9381040 for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
9391041 struct ieee80211_link_sta *link_sta;
9401042 struct mt792x_link_sta *mlink;
1043+ bool is_deflink = false;
9411044
9421045 if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
9431046 mlink = &msta->deflink;
944− msta->deflink_id = link_id;
1047+ is_deflink = true;
9451048 } else {
946− mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink), GFP_KERNEL);
1049+ mlink = kzalloc(sizeof(*mlink), GFP_KERNEL);
9471050 if (!mlink) {
9481051 err = -ENOMEM;
9491052 break;
9501053 }
9511054 }
9521055
953− msta->valid_links |= BIT(link_id);
954− rcu_assign_pointer(msta->link[link_id], mlink);
9551056 mlink->sta = msta;
9561057 mlink->pri_link = &sta->deflink;
9571058 mlink->wcid.def_wcid = &msta->deflink.wcid;
9581059
9591060 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);
9611075 }
9621076
1077+ if (err && added_links)
1078+ mt7925_mac_sta_unwind_links_host(dev, sta, added_links);
1079+
9631080 return err;
9641081 }
9651082
@@ -981,7 +1098,8 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, · 15 unmodified lines
9811098
9821099 err = mt7925_mac_sta_add_links(dev, vif, sta, sta->valid_links);
9831100 } 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);
9851103 }
9861104
9871105 return err;
@@ -1030,11 +1148,11 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev, · 42 unmodified lines
10301148 struct mt792x_link_sta *mlink;
10311149 struct mt792x_sta *msta;
10321150
1151+ mt792x_mutex_acquire(dev);
1152+
10331153 msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
10341154 mlink = mt792x_sta_to_link(msta, link_sta->link_id);
10351155
1036− mt792x_mutex_acquire(dev);
1037−
10381156 if (ieee80211_vif_is_mld(vif)) {
10391157 link_conf = mt792x_vif_to_bss_conf(vif, msta->deflink_id);
10401158 } else {
@@ -1055,7 +1173,8 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev, · 14 unmodified lines
10551173 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
10561174 memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac));
10571175
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);
10591178
10601179 mt792x_mutex_release(dev);
10611180 }
@@ -1083,23 +1202,21 @@ EXPORT_SYMBOL_GPL(mt7925_mac_sta_event); · 21 unmodified lines
10831202
10841203 static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
10851204 struct ieee80211_vif *vif,
1086− struct ieee80211_link_sta *link_sta)
1205+ struct ieee80211_link_sta *link_sta,
1206+ struct mt792x_link_sta *mlink)
10871207 {
10881208 struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1209+ struct mt76_wcid *wcid = &mlink->wcid;
10891210 struct ieee80211_bss_conf *link_conf;
10901211 u8 link_id = link_sta->link_id;
1091− struct mt792x_link_sta *mlink;
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);
1212+ u16 idx = wcid->idx;
10961213
10971214 mt7925_roc_abort_sync(dev);
10981215
1099− mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid);
1216+ mt76_connac_free_pending_tx_skbs(&dev->pm, wcid);
11001217 mt76_connac_pm_wake(&dev->mphy, &dev->pm);
11011218
1102− mt7925_mcu_sta_update(dev, link_sta, vif, false,
1219+ mt7925_mcu_sta_update(dev, link_sta, vif, mlink, false,
11031220 MT76_STA_INFO_STATE_NONE);
11041221 mt7925_mac_wtbl_update(dev, mlink->wcid.idx,
11051222 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -1123,6 +1240,10 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev, · 17 unmodified lines
11231240 list_del_init(&mlink->wcid.poll_list);
11241241 spin_unlock_bh(&mdev->sta_poll_lock);
11251242
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+
11261247 mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
11271248 }
11281249
@@ -1132,7 +1253,6 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, · 3 unmodified lines
11321253 {
11331254 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
11341255 struct mt76_dev *mdev = &dev->mt76;
1135− struct mt76_wcid *wcid;
11361256 unsigned int link_id;
11371257
11381258 /* 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
11711291 if (!link_sta)
11721292 continue;
11731293
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));
11751296 if (!mlink)
11761297 continue;
11771298
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);
11821299 msta->valid_links &= ~BIT(link_id);
11831300 mlink->sta = NULL;
11841301 mlink->pri_link = NULL;
11851302
1186− if (link_sta != mlink->pri_link) {
1187− mt76_wcid_cleanup(mdev, wcid);
1188− mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx);
1189− }
1303+ mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta, mlink);
1304+
1305+ if (mlink != &msta->deflink)
1306+ kfree_rcu(mlink, rcu_head);
11901307
11911308 if (msta->deflink_id == link_id)
11921309 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
@@ -1323,10 +1440,18 @@ void mt7925_mlo_pm_work(struct work_struct *work) · 130 unmodified lines
13231440 void mt7925_scan_work(struct work_struct *work)
13241441 {
13251442 struct mt792x_phy *phy;
1443+ struct mt792x_dev *dev;
1444+ struct mt76_connac_pm *pm;
13261445
13271446 phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,
13281447 scan_work.work);
13291448
1449+ dev = phy->dev;
1450+ pm = &dev->pm;
1451+
1452+ if (pm->suspended)
1453+ return;
1454+
13301455 while (true) {
13311456 struct sk_buff *skb;
13321457 struct tlv *tlv;
@@ -1544,8 +1669,10 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, · 211 unmodified lines
15441669 valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0);
15451670
15461671 for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
1672+ struct mt792x_bss_conf *mconf;
15471673 struct mt792x_link_sta *mlink;
15481674
1675+ mconf = mt792x_vif_to_link(mvif, i);
15491676 mlink = mt792x_sta_to_link(msta, i);
15501677
15511678 if (enabled)
@@ -1556,7 +1683,7 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, · 4 unmodified lines
15561683 if (!mlink->wcid.sta)
15571684 continue;
15581685
1559− mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i);
1686+ mt7925_mcu_wtbl_update_hdr_trans(dev, vif, mconf, mlink);
15601687 }
15611688
15621689 mt792x_mutex_release(dev);
@@ -1716,7 +1843,8 @@ mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 153 unmodified lines
17161843 if (err)
17171844 goto out;
17181845
1719− err = mt7925_mcu_sta_update(dev, NULL, vif, true,
1846+ err = mt7925_mcu_sta_update(dev, NULL, vif,
1847+ &mvif->sta.deflink, true,
17201848 MT76_STA_INFO_STATE_NONE);
17211849 out:
17221850 mt792x_mutex_release(dev);
@@ -1749,6 +1877,10 @@ static int · 26 unmodified lines
17491877 mt7925_add_chanctx(struct ieee80211_hw *hw,
17501878 struct ieee80211_chanctx_conf *ctx)
17511879 {
1880+ struct mt792x_dev *dev = mt792x_hw_dev(hw);
1881+
1882+ dev->new_ctx = ctx;
1883+
17521884 return 0;
17531885 }
17541886
@@ -1756,6 +1888,11 @@ static void · 1 unmodified line
17561888 mt7925_remove_chanctx(struct ieee80211_hw *hw,
17571889 struct ieee80211_chanctx_conf *ctx)
17581890 {
1891+ struct mt792x_dev *dev = mt792x_hw_dev(hw);
1892+
1893+ if (dev->new_ctx == ctx)
1894+ dev->new_ctx = NULL;
1895+
17591896 }
17601897
17611898 static void
@@ -1850,7 +1987,8 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw, · 88 unmodified lines
18501987 mt792x_mutex_acquire(dev);
18511988
18521989 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,
18541992 MT76_STA_INFO_STATE_ASSOC);
18551993 mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
18561994
@@ -1894,10 +2032,8 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw, · 37 unmodified lines
18942032 struct mt792x_phy *phy = mt792x_hw_phy(hw);
18952033 struct mt792x_dev *dev = mt792x_hw_dev(hw);
18962034 struct mt792x_bss_conf *mconf;
1897− struct ieee80211_bss_conf *link_conf;
18982035
18992036 mconf = mt792x_vif_to_link(mvif, info->link_id);
1900− link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);
19012037
19022038 mt792x_mutex_acquire(dev);
19032039
@@ -1939,10 +2075,6 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw, · 35 unmodified lines
19392075 mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS;
19402076 }
19412077
1942− if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)
1943− mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76,
1944− link_conf, NULL);
1945−
19462078 if (changed & BSS_CHANGED_CQM)
19472079 mt7925_mcu_set_rssimonitor(dev, vif);
19482080
@@ -2144,6 +2276,11 @@ static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw, · 195 unmodified lines
21442276 mctx->bss_conf = NULL;
21452277 mconf->mt76.ctx = NULL;
21462278 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+ }
21472284 }
21482285
21492286 static void mt7925_rfkill_poll(struct ieee80211_hw *hw)
@@ -2158,6 +2295,121 @@ static void mt7925_rfkill_poll(struct ieee80211_hw *hw) · 8 unmodified lines
21582295 wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0);
21592296 }
21602297
2298+static 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+
2307+void 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+
2349+static 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+
2366+static 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+
2382+static 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+
2392+static 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+
21612413 const struct ieee80211_ops mt7925_ops = {
21622414 .tx = mt792x_tx,
21632415 .start = mt7925_start,
@@ -2221,6 +2473,12 @@ const struct ieee80211_ops mt7925_ops = { · 57 unmodified lines
22212473 .change_vif_links = mt7925_change_vif_links,
22222474 .change_sta_links = mt7925_change_sta_links,
22232475 .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,
22242482 };
22252483 EXPORT_SYMBOL_GPL(mt7925_ops);
22262484
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c+106−88
@@ -1066,9 +1066,8 @@ EXPORT_SYMBOL_GPL(mt7925_run_firmware); · 1065 unmodified lines
10661066 static void
10671067 mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
10681068 struct ieee80211_vif *vif,
1069− struct ieee80211_link_sta *link_sta)
1069+ struct mt792x_link_sta *mlink)
10701070 {
1071− struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
10721071 struct sta_rec_hdr_trans *hdr_trans;
10731072 struct mt76_wcid *wcid;
10741073 struct tlv *tlv;
@@ -1082,19 +1081,11 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb, · 7 unmodified lines
10821081 else
10831082 hdr_trans->from_ds = true;
10841083
1085− if (link_sta) {
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)
1084+ if (WARN_ON_ONCE(!mlink))
10961085 return;
10971086
1087+ wcid = &mlink->wcid;
1088+
10981089 hdr_trans->dis_rx_hdr_tran = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
10991090 if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {
11001091 hdr_trans->to_ds = true;
@@ -1104,30 +1095,18 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb, · 3 unmodified lines
11041095
11051096 int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
11061097 struct ieee80211_vif *vif,
1107− struct ieee80211_sta *sta,
1108− int link_id)
1098+ struct mt792x_bss_conf *mconf,
1099+ struct mt792x_link_sta *mlink)
11091100 {
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;
11151101 struct sk_buff *skb;
11161102
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−
11231103 skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mconf->mt76,
11241104 &mlink->wcid,
11251105 MT7925_STA_UPDATE_MAX_SIZE);
11261106 if (IS_ERR(skb))
11271107 return PTR_ERR(skb);
11281108
1129− /* starec hdr trans */
1130− mt7925_mcu_sta_hdr_trans_tlv(skb, vif, link_sta);
1109+ mt7925_mcu_sta_hdr_trans_tlv(skb, vif, mlink);
11311110 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
11321111 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
11331112 }
@@ -1288,14 +1267,16 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, · 154 unmodified lines
12881267 return PTR_ERR(skb);
12891268
12901269 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);
12921272 return ret;
1273+ }
12931274
12941275 return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
12951276 }
12961277
1297−int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
1298− int duration, u8 token_id)
1278+int mt7925_mcu_set_mlo_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
1279+ u16 sel_links, int duration, u8 token_id)
12991280 {
13001281 struct mt792x_vif *mvif = mconf->vif;
13011282 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
13301311 .roc[1].len = cpu_to_le16(sizeof(struct roc_acquire_tlv))
13311312 };
13321313
1314+ struct wiphy *wiphy = phy->mt76->hw->wiphy;
1315+
13331316 if (!mconf || hweight16(vif->valid_links) < 2 ||
13341317 hweight16(sel_links) != 2)
13351318 return -EPERM;
@@ -1352,7 +1335,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, · 16 unmodified lines
13521335 is_AG_band |= links[i].chan->band == NL80211_BAND_2GHZ;
13531336 }
13541337
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))
13561340 type = is_AG_band ? MT7925_ROC_REQ_MLSR_AG :
13571341 MT7925_ROC_REQ_MLSR_AA;
13581342 else
@@ -1721,10 +1705,9 @@ mt7925_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta) · 362 unmodified lines
17211705 static void
17221706 mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb,
17231707 struct ieee80211_vif *vif,
1724− struct ieee80211_link_sta *link_sta)
1708+ struct ieee80211_link_sta *link_sta,
1709+ struct mt792x_link_sta *mlink)
17251710 {
1726− struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
1727− struct mt792x_link_sta *mlink;
17281711 struct sta_rec_amsdu *amsdu;
17291712 struct tlv *tlv;
17301713
@@ -1740,7 +1723,6 @@ mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb, · 9 unmodified lines
17401723 amsdu->max_amsdu_num = 8;
17411724 amsdu->amsdu_en = true;
17421725
1743− mlink = mt792x_sta_to_link(msta, link_sta->link_id);
17441726 mlink->wcid.amsdu = true;
17451727
17461728 switch (link_sta->agg.max_amsdu_len) {
@@ -1911,36 +1893,53 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb, · 164 unmodified lines
19111893
19121894 static void
19131895 mt7925_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)
19151900 {
19161901 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
19171902 struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
1918− unsigned long valid = mvif->valid_links;
1919− struct mt792x_bss_conf *mconf;
1920− struct mt792x_link_sta *mlink;
1903+ struct mt792x_dev *dev = mvif->phy->dev;
1904+ struct mt792x_bss_conf *mconf_pri;
19211905 struct sta_rec_mld *mld;
19221906 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+ }
19241923
19251924 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD, sizeof(*mld));
19261925 mld = (struct sta_rec_mld *)tlv;
19271926 memcpy(mld->mac_addr, sta->addr, ETH_ALEN);
1927+
19281928 mld->primary_id = cpu_to_le16(msta->deflink.wcid.idx);
19291929 mld->wlan_id = cpu_to_le16(msta->deflink.wcid.idx);
1930− mld->link_num = min_t(u8, hweight16(mvif->valid_links), 2);
19311930
1932− for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
1933− if (cnt == mld->link_num)
1934− break;
1931+ /* Always encode primary link first. */
1932+ mld->link[cnt].wlan_id = cpu_to_le16(msta->deflink.wcid.idx);
1933+ mld->link[cnt++].bss_idx = mconf_pri->mt76.idx;
19351934
1936− mconf = mt792x_vif_to_link(mvif, i);
1937− mlink = mt792x_sta_to_link(msta, i);
1935+ /* Optionally encode the currently-updated secondary link. */
1936+ if (mlink && mlink != &msta->deflink && mconf) {
1937+ mld->secondary_id = cpu_to_le16(mlink->wcid.idx);
19381938 mld->link[cnt].wlan_id = cpu_to_le16(mlink->wcid.idx);
19391939 mld->link[cnt++].bss_idx = mconf->mt76.idx;
1940−
1941− if (mlink != &msta->deflink)
1942− mld->secondary_id = cpu_to_le16(mlink->wcid.idx);
19431940 }
1941+
1942+ mld->link_num = cnt;
19441943 }
19451944
19461945 static void
@@ -1961,10 +1960,12 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 14 unmodified lines
19611960 struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv;
19621961 struct mt76_dev *dev = phy->dev;
19631962 struct mt792x_bss_conf *mconf;
1963+ struct mt792x_link_sta *mlink;
19641964 struct sk_buff *skb;
19651965 int conn_state;
19661966
19671967 mconf = mt792x_vif_to_link(mvif, info->wcid->link_id);
1968+ mlink = container_of(info->wcid, struct mt792x_link_sta, wcid);
19681969
19691970 skb = __mt76_connac_mcu_alloc_sta_req(dev, &mconf->mt76, info->wcid,
19701971 MT7925_STA_UPDATE_MAX_SIZE);
@@ -1982,7 +1983,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 11 unmodified lines
19821983 mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
19831984 mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
19841985 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);
19861987 mt7925_mcu_sta_he_tlv(skb, info->link_sta);
19871988 mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta);
19881989 mt7925_mcu_sta_eht_tlv(skb, info->link_sta);
@@ -1993,7 +1994,10 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 4 unmodified lines
19931994 info->state);
19941995
19951996 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+
19972001 mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta);
19982002 }
19992003 }
@@ -2003,7 +2007,10 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 3 unmodified lines
20032007 mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF,
20042008 sizeof(struct tlv));
20052009 } 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);
20072014 }
20082015
20092016 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
20112018
20122019 int mt7925_mcu_sta_update(struct mt792x_dev *dev,
20132020 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,
20152024 enum mt76_sta_info_state state)
20162025 {
20172026 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
20262035 .offload_fw = true,
20272036 .rcpi = to_rcpi(rssi),
20282037 };
2029− struct mt792x_sta *msta;
2030− struct mt792x_link_sta *mlink;
20312038
2032− if (link_sta) {
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;
2039+ info.wcid = &mlink->wcid;
20372040 info.newly = state != MT76_STA_INFO_STATE_ASSOC;
20382041
20392042 return mt7925_mcu_sta_cmd(&dev->mphy, &info);
@@ -2470,7 +2473,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, · 430 unmodified lines
24702473 struct ieee80211_bss_conf *link_conf,
24712474 struct ieee80211_link_sta *link_sta,
24722475 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,
24742479 bool enable)
24752480 {
24762481 struct ieee80211_vif *vif = link_conf->vif;
@@ -2479,7 +2484,6 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, · 2 unmodified lines
24792484 &link_conf->chanreq.oper;
24802485 enum nl80211_band band = chandef->chan->band;
24812486 struct mt76_connac_bss_basic_tlv *basic_req;
2482− struct mt792x_link_sta *mlink;
24832487 struct tlv *tlv;
24842488 int conn_type;
24852489 u8 idx;
@@ -2503,20 +2507,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, · 17 unmodified lines
25032507 basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, link_sta);
25042508 basic_req->bcn_interval = cpu_to_le16(link_conf->beacon_int);
25052509 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);
25072511 basic_req->link_idx = mconf->mt76.idx;
2508−
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);
2512+ basic_req->sta_idx = cpu_to_le16(sta_wlan_idx);
25202513 basic_req->omac_idx = mconf->mt76.omac_idx;
25212514 basic_req->band_idx = mconf->mt76.band_idx;
25222515 basic_req->wmm_idx = mconf->mt76.wmm_idx;
@@ -2823,16 +2816,16 @@ void mt7925_mcu_del_dev(struct mt76_dev *mdev, · 300 unmodified lines
28232816 &dev_req, sizeof(dev_req), true);
28242817 }
28252818
2826−int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
2827− struct ieee80211_chanctx_conf *ctx,
2828− struct ieee80211_bss_conf *link_conf,
2829− struct ieee80211_link_sta *link_sta,
2830− int enable)
2819+int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
2820+ struct ieee80211_chanctx_conf *ctx,
2821+ struct ieee80211_bss_conf *link_conf,
2822+ struct ieee80211_link_sta *link_sta,
2823+ u16 bmc_tx_wlan_idx,
2824+ u16 sta_wlan_idx,
2825+ int enable)
28312826 {
2832− struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
28332827 struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
28342828 struct mt792x_dev *dev = phy->dev;
2835− struct mt792x_link_sta *mlink_bc;
28362829 struct sk_buff *skb;
28372830
28382831 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
28402833 if (IS_ERR(skb))
28412834 return PTR_ERR(skb);
28422835
2843− mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
2844−
28452836 /* bss_basic must be first */
28462837 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);
28482839 mt7925_mcu_bss_sec_tlv(skb, link_conf);
28492840 mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, link_conf);
28502841 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
28652856 MCU_UNI_CMD(BSS_INFO_UPDATE), true);
28662857 }
28672858
2859+int 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+
28682886 int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
28692887 {
28702888 struct mt76_dev *mdev = phy->dev;
@@ -3375,7 +3393,6 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, · 504 unmodified lines
33753393 u8 rsvd[64];
33763394 } __packed req = {
33773395 .tag = cpu_to_le16(0x3),
3378− .len = cpu_to_le16(sizeof(req) - 4),
33793396
33803397 .idx = idx,
33813398 .env = env_cap,
@@ -3404,6 +3421,7 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, · 22 unmodified lines
34043421 memcpy(req.type, rule->type, 2);
34053422
34063423 req.size = cpu_to_le16(seg->len);
3424+ req.len = cpu_to_le16(sizeof(req) + seg->len - 4);
34073425 dev->phy.clc_chan_conf = clc->ver == 1 ? 0xff : rule->flag;
34083426 skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,
34093427 le16_to_cpu(req.size) + sizeof(req),
@@ -3727,7 +3745,7 @@ mt7925_mcu_rate_txpower_band(struct mt76_phy *phy, · 317 unmodified lines
37273745 memcpy(tx_power_tlv->alpha2, dev->alpha2, sizeof(dev->alpha2));
37283746 tx_power_tlv->n_chan = num_ch;
37293747 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);
37313749
37323750 switch (band) {
37333751 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
693693 struct ieee80211_bss_conf *link_conf,
694694 struct ieee80211_link_sta *link_sta,
695695 int enable);
696+int 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);
696703 int mt7925_mcu_set_timing(struct mt792x_phy *phy,
697704 struct ieee80211_bss_conf *link_conf);
698705 int 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
250250 bool enable);
251251 int mt7925_mcu_sta_update(struct mt792x_dev *dev,
252252 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,
254256 enum mt76_sta_info_state state);
255257 int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag);
256258 int 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
298300 void mt7925_mlo_pm_work(struct work_struct *work);
299301 void mt7925_scan_work(struct work_struct *work);
300302 void mt7925_roc_work(struct work_struct *work);
303+void mt7925_csa_work(struct work_struct *work);
301304 int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev,
302305 struct ieee80211_bss_conf *link_conf);
303306 void mt7925_coredump_work(struct work_struct *work);
@@ -349,8 +352,8 @@ int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw, · 45 unmodified lines
349352 int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set);
350353 int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
351354 enum environment_cap env_cap);
352−int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
353− int duration, u8 token_id);
355+int mt7925_mcu_set_mlo_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
356+ u16 sel_links, int duration, u8 token_id);
354357 int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
355358 struct ieee80211_channel *chan, int duration,
356359 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
367370 int mt7925_mcu_set_rts_thresh(struct mt792x_phy *phy, u32 val);
368371 int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
369372 struct ieee80211_vif *vif,
370− struct ieee80211_sta *sta,
371− int link_id);
373+ struct mt792x_bss_conf *mconf,
374+ struct mt792x_link_sta *mlink);
372375 int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy);
373376
374377 int 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
232232 dev->regd_user)
233233 return -EINVAL;
234234
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'))
236237 return 0;
237238
238239 /* 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
4141 #define MT792x_MCU_INIT_RETRY_COUNT 10
4242 #define MT792x_WFSYS_INIT_RETRY_COUNT 2
4343
44+#define MT7902_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7902_1.bin"
4445 #define MT7920_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1a.bin"
4546 #define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
4647 #define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
4748 #define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"
4849
50+#define MT7902_ROM_PATCH "mediatek/WIFI_MT7902_patch_mcu_1_1_hdr.bin"
4951 #define MT7920_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.bin"
5052 #define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
5153 #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
9597
9698 struct mt792x_link_sta {
9799 struct mt76_wcid wcid; /* must be first */
100+ struct rcu_head rcu_head;
98101
99102 u32 airtime_ac[8];
100103
@@ -448,6 +451,8 @@ void mt792x_config_mac_addr_list(struct mt792x_dev *dev); · 347 unmodified lines
448451 static inline char *mt792x_ram_name(struct mt792x_dev *dev)
449452 {
450453 switch (mt76_chip(&dev->mt76)) {
454+ case 0x7902:
455+ return MT7902_FIRMWARE_WM;
451456 case 0x7920:
452457 return MT7920_FIRMWARE_WM;
453458 case 0x7922:
@@ -462,6 +467,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev) · 8 unmodified lines
462467 static inline char *mt792x_patch_name(struct mt792x_dev *dev)
463468 {
464469 switch (mt76_chip(&dev->mt76)) {
470+ case 0x7902:
471+ return MT7902_ROM_PATCH;
465472 case 0x7920:
466473 return MT7920_ROM_PATCH;
467474 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
151151 cancel_work_sync(&dev->reset_work);
152152 mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
153153
154− if (is_mt7921(&dev->mt76)) {
154+ if (is_connac2(&dev->mt76)) {
155155 mt792x_mutex_acquire(dev);
156156 mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
157157 mt792x_mutex_release(dev);
@@ -691,9 +691,8 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw) · 533 unmodified lines
691691 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
692692 ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
693693
694− if (is_mt7921(&dev->mt76)) {
695− ieee80211_hw_set(hw, CHANCTX_STA_CSA);
696− }
694+ ieee80211_hw_set(hw, CHANCTX_STA_CSA);
695+
697696
698697 if (dev->pm.enable)
699698 ieee80211_hw_set(hw, CONNECTION_MONITOR);
@@ -927,6 +926,13 @@ int mt792x_load_firmware(struct mt792x_dev *dev) · 227 unmodified lines
927926 {
928927 int ret;
929928
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+
930936 ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev));
931937 if (ret)
932938 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
103103 mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10));
104104 mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4));
105105 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));
106122 } else {
107123 /* rx ring */
108124 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
356372
357373 int mt792x_wfsys_reset(struct mt792x_dev *dev)
358374 {
359− u32 addr = is_mt7921(&dev->mt76) ? 0x18000140 : 0x7c000140;
375+ u32 addr = is_connac2(&dev->mt76) ? 0x18000140 : 0x7c000140;
360376
361377 mt76_clear(dev, addr, WFSYS_SW_RST_B);
362378 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
375375 }
376376
377377 if (!mt792x_mcu_fw_pmctrl(dev)) {
378− cancel_delayed_work_sync(&mphy->mac_work);
378+ cancel_delayed_work(&mphy->mac_work);
379379 return;
380380 }
381381 out:
drivers/net/wireless/mediatek/mt76/mt792x_regs.h+6−0
@@ -25,6 +25,8 @@ · 24 unmodified lines
2525 #define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))
2626 #define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
2727
28+#define MT_PSE_BASE 0x820c8000
29+
2830 /* TMAC: band 0(0x21000), band 1(0xa1000) */
2931 #define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000)
3032 #define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
@@ -390,6 +392,10 @@ · 359 unmodified lines
390392 #define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600)
391393 #define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)
392394
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+
393399 #define MT_HW_BOUND 0x70010020
394400 #define MT_HW_CHIPID 0x70010200
395401 #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
206206 mt792xu_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
207207 }
208208
209+struct 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+
218+static 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+
227+static 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+
209236 int mt792xu_dma_init(struct mt792x_dev *dev, bool resume)
210237 {
211238 int err;
@@ -236,25 +263,33 @@ EXPORT_SYMBOL_GPL(mt792xu_dma_init); · 24 unmodified lines
236263
237264 int mt792xu_wfsys_reset(struct mt792x_dev *dev)
238265 {
266+ const struct mt792xu_wfsys_desc *desc = is_mt7925(&dev->mt76) ?
267+ &mt7925_wfsys_desc :
268+ &mt7921_wfsys_desc;
239269 u32 val;
240270 int i;
241271
242272 mt792xu_epctl_rst_opt(dev, false);
243273
244− val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
274+ val = mt792xu_uhw_rr(&dev->mt76, desc->rst_reg);
245275 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);
247277
248− usleep_range(10, 20);
278+ if (desc->delay_ms)
279+ msleep(desc->delay_ms);
280+ else
281+ usleep_range(10, 20);
249282
250− val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
283+ val = mt792xu_uhw_rr(&dev->mt76, desc->rst_reg);
251284 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);
253289
254− mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
255290 for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) {
256− val = mt792xu_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);
257− if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)
291+ val = mt792xu_uhw_rr(&dev->mt76, desc->done_reg);
292+ if ((val & desc->done_mask) == desc->done_val)
258293 break;
259294
260295 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
226226 #define RADAR_BACKGROUND 2
227227 struct mt7996_dev *dev = data;
228228 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;
230231
231232 if (!phy || !val || val > RADAR_BACKGROUND)
232233 return -EINVAL;
233234
234− if (val == RADAR_BACKGROUND && !dev->rdd2_phy) {
235− dev_err(dev->mt76.dev, "Background radar is not enabled\n");
236− return -EINVAL;
235+ if (test_bit(MT76_SCANNING, &phy->mt76->state))
236+ return -EBUSY;
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;
237246 }
238247
239248 rdd_idx = mt7996_get_rdd_idx(phy, val == RADAR_BACKGROUND);
@@ -242,6 +251,11 @@ mt7996_radar_trigger(void *data, u64 val) · 2 unmodified lines
242251 return -EINVAL;
243252 }
244253
254+ ret = cfg80211_chandef_dfs_required(dev->mt76.hw->wiphy, chandef,
255+ NL80211_IFTYPE_AP);
256+ if (ret <= 0)
257+ return ret;
258+
245259 return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, rdd_idx, 0);
246260 }
247261
@@ -626,13 +640,18 @@ mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta) · 378 unmodified lines
626640 {
627641 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
628642 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);
630644 struct ieee80211_link_sta *link_sta;
631645 struct seq_file *s = data;
632646 struct ieee80211_vif *vif;
647+ struct mt7996_dev *dev;
633648 unsigned int link_id;
634649
650+ if (!phy)
651+ return;
652+
635653 vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
654+ dev = phy->dev;
636655
637656 rcu_read_lock();
638657
@@ -979,13 +998,17 @@ static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file, · 340 unmodified lines
979998 #define LONG_PREAMBLE 1
980999 struct ieee80211_link_sta *link_sta = file->private_data;
9811000 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);
9831002 struct mt7996_sta_link *msta_link;
9841003 struct ra_rate phy = {};
1004+ struct mt7996_dev *dev;
9851005 char buf[100];
9861006 int ret;
9871007 u16 gi, ltf;
9881008
1009+ if (!link_phy)
1010+ return -EINVAL;
1011+
9891012 if (count >= sizeof(buf))
9901013 return -EINVAL;
9911014
@@ -1008,6 +1031,7 @@ static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file, · 16 unmodified lines
10081031 * spe - off: 0, on: 1
10091032 * ltf - 1xltf: 0, 2xltf: 1, 4xltf: 2
10101033 */
1034+ dev = link_phy->dev;
10111035 if (sscanf(buf, "%hhu %hhu %hhu %hhu %hu %hhu %hhu %hhu %hhu %hu",
10121036 &phy.mode, &phy.bw, &phy.mcs, &phy.nss, &gi,
10131037 &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
128128
129129 /* data tx queue */
130130 if (is_mt7996(&dev->mt76)) {
131− TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
132131 if (dev->hif2) {
133− /* default bn1:ring19 bn2:ring21 */
134− TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1,
135− MT7996_TXQ_BAND1);
136− TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2,
137− MT7996_TXQ_BAND2);
132+ if (mt76_npu_device_active(&dev->mt76)) {
133+ TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND2,
134+ MT7996_TXQ_BAND2);
135+ TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND0,
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+ }
138148 } else {
139149 /* single pcie bn0/1:ring18 bn2:ring19 */
150+ TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0,
151+ MT7996_TXQ_BAND0);
140152 TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND1,
141153 MT7996_TXQ_BAND1);
142154 }
@@ -350,6 +362,9 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) · 207 unmodified lines
350362 if (!mt7996_has_wa(dev) || mt76_npu_device_active(&dev->mt76))
351363 irq_mask &= ~(MT_INT_RX(MT_RXQ_MAIN_WA) |
352364 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));
353368 irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
354369
355370 mt7996_irq_enable(dev, irq_mask);
@@ -430,39 +445,48 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) · 74 unmodified lines
430445 MT_WFDMA_HOST_CONFIG_BAND1_PCIE1 |
431446 MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
432447
433− if (is_mt7996(&dev->mt76))
434− mt76_set(dev, MT_WFDMA_HOST_CONFIG,
435− MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
436− else
448+ if (is_mt7996(&dev->mt76)) {
449+ if (mt76_npu_device_active(&dev->mt76))
450+ mt76_set(dev, MT_WFDMA_HOST_CONFIG,
451+ 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 {
437456 mt76_set(dev, MT_WFDMA_HOST_CONFIG,
438457 MT_WFDMA_HOST_CONFIG_BAND1_PCIE1);
458+ }
439459
440460 /* AXI read outstanding number */
441461 mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL,
442462 MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK, 0x14);
443463
444− if (dev->hif2->speed < PCIE_SPEED_5_0GT ||
445− (dev->hif2->speed == PCIE_SPEED_5_0GT &&
446− dev->hif2->width < PCIE_LNK_X2)) {
447− mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
448− WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
449− FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
450− 0x1));
451− mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
452− MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
453− FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
454− 0x1));
455− } else if (dev->hif2->speed < PCIE_SPEED_8_0GT ||
456− (dev->hif2->speed == PCIE_SPEED_8_0GT &&
457− dev->hif2->width < PCIE_LNK_X2)) {
458− mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
459− WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
460− FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
461− 0x2));
462− mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
463− MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
464− FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
465− 0x2));
464+ if (!is_mt7996(&dev->mt76) ||
465+ !mt76_npu_device_active(&dev->mt76)) {
466+ if (dev->hif2->speed < PCIE_SPEED_5_0GT ||
467+ (dev->hif2->speed == PCIE_SPEED_5_0GT &&
468+ dev->hif2->width < PCIE_LNK_X2)) {
469+ mt76_rmw(dev,
470+ WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
471+ WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
472+ FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
473+ 0x1));
474+ mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
475+ MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
476+ FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
477+ 0x1));
478+ } else if (dev->hif2->speed < PCIE_SPEED_8_0GT ||
479+ (dev->hif2->speed == PCIE_SPEED_8_0GT &&
480+ dev->hif2->width < PCIE_LNK_X2)) {
481+ mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
482+ WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
483+ FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
484+ 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+ }
466490 }
467491
468492 /* WFDMA rx threshold */
@@ -497,7 +521,7 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) · 28 unmodified lines
497521 int mt7996_dma_rro_init(struct mt7996_dev *dev)
498522 {
499523 struct mt76_dev *mdev = &dev->mt76;
500− u32 irq_mask;
524+ u32 size;
501525 int ret;
502526
503527 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
524548 mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C],
525549 true);
526550 }
527− goto start_hw_rro;
551+
552+ return 0;
528553 }
529554
530555 /* ind cmd */
@@ -545,10 +570,12 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev) · 14 unmodified lines
545570 if (mtk_wed_device_active(&mdev->mmio.wed) &&
546571 mtk_wed_get_rx_capa(&mdev->mmio.wed))
547572 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;
548576 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0],
549577 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),
550− MT7996_RX_RING_SIZE,
551− MT7996_RX_MSDU_PAGE_SIZE,
578+ size, MT7996_RX_MSDU_PAGE_SIZE,
552579 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));
553580 if (ret)
554581 return ret;
@@ -560,10 +587,12 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev) · 5 unmodified lines
560587 if (mtk_wed_device_active(&mdev->mmio.wed) &&
561588 mtk_wed_get_rx_capa(&mdev->mmio.wed))
562589 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;
563593 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1],
564594 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),
565− MT7996_RX_RING_SIZE,
566− MT7996_RX_MSDU_PAGE_SIZE,
595+ size, MT7996_RX_MSDU_PAGE_SIZE,
567596 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));
568597 if (ret)
569598 return ret;
@@ -576,52 +605,60 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev) · 6 unmodified lines
576605 if (mtk_wed_device_active(&mdev->mmio.wed) &&
577606 mtk_wed_get_rx_capa(&mdev->mmio.wed))
578607 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;
579611 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2],
580612 MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),
581− MT7996_RX_RING_SIZE,
582− MT7996_RX_MSDU_PAGE_SIZE,
613+ size, MT7996_RX_MSDU_PAGE_SIZE,
583614 MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));
584615 if (ret)
585616 return ret;
586617 }
587618
588−start_hw_rro:
589− if (mtk_wed_device_active(&mdev->mmio.wed)) {
590− irq_mask = mdev->mmio.irqmask |
619+ return 0;
620+}
621+
622+void 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 |
591628 MT_INT_TX_DONE_BAND2;
592629
593630 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);
595633 mt7996_irq_enable(dev, irq_mask);
596− } else {
597− if (is_mt7996(&dev->mt76)) {
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− }
634+ return;
635+ }
608636
609− mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND0, mt76_dma_rx_poll);
610− if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
611− mt76_queue_rx_init(dev, MT_RXQ_RRO_RXDMAD_C,
612− mt76_dma_rx_poll);
613− } else {
614− mt76_queue_rx_init(dev, MT_RXQ_RRO_IND,
615− mt76_dma_rx_poll);
616− mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND0,
617− mt76_dma_rx_poll);
618− }
637+ if (is_mt7996(&dev->mt76)) {
638+ mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND1,
639+ mt76_dma_rx_poll);
640+ mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND2,
641+ mt76_dma_rx_poll);
642+ mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND2,
643+ mt76_dma_rx_poll);
644+ } else {
645+ mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND1,
646+ mt76_dma_rx_poll);
647+ }
619648
620− if (!mt76_npu_device_active(&dev->mt76))
621− mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE);
649+ mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND0, mt76_dma_rx_poll);
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);
622658 }
623659
624− return 0;
660+ if (!mt76_npu_device_active(&dev->mt76))
661+ mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE);
625662 }
626663
627664 int mt7996_dma_init(struct mt7996_dev *dev)
@@ -642,11 +679,16 @@ int mt7996_dma_init(struct mt7996_dev *dev) · 14 unmodified lines
642679 mt7996_dma_disable(dev, true);
643680
644681 /* init tx queue */
645− ret = mt7996_init_tx_queues(&dev->phy,
646− MT_TXQ_ID(dev->mphy.band_idx),
647− MT7996_TX_RING_SIZE,
648− MT_TXQ_RING_BASE(0),
649− wed);
682+ if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76))
683+ ret = mt7996_init_tx_queues(&dev->phy, MT_TXQ_ID(0),
684+ MT7996_NPU_TX_RING_SIZE,
685+ MT_TXQ_RING_BASE(0) + hif1_ofs,
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);
650692 if (ret)
651693 return ret;
652694
@@ -714,6 +756,9 @@ int mt7996_dma_init(struct mt7996_dev *dev) · 61 unmodified lines
714756 (is_mt7992(&dev->mt76)))) {
715757 dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
716758 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);
717762 }
718763
719764 if (mt7996_has_wa(dev)) {
@@ -846,6 +891,8 @@ int mt7996_dma_init(struct mt7996_dev *dev) · 126 unmodified lines
846891 /* tx free notify event from WA for band0 */
847892 dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
848893 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);
849896 }
850897
851898 ret = mt76_queue_alloc(dev,
@@ -859,16 +906,21 @@ int mt7996_dma_init(struct mt7996_dev *dev) · 7 unmodified lines
859906 }
860907
861908 if (mt7996_band_valid(dev, MT_BAND2)) {
909+ u32 size;
910+
862911 /* rx rro data queue for band2 */
863912 dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags =
864913 MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;
865914 if (mtk_wed_device_active(wed) &&
866915 mtk_wed_get_rx_capa(wed))
867916 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;
868921 ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
869922 MT_RXQ_ID(MT_RXQ_RRO_BAND2),
870− MT7996_RX_RING_SIZE,
871− MT7996_RX_BUF_SIZE,
923+ size, MT7996_RX_BUF_SIZE,
872924 MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);
873925 if (ret)
874926 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
3333 if (dev->var.fem == MT7996_FEM_INT)
3434 return MT7992_EEPROM_DEFAULT_23_INT;
3535 return MT7992_EEPROM_DEFAULT_23;
36+ case MT7992_VAR_TYPE_24:
37+ return MT7992_EEPROM_DEFAULT_24;
3638 case MT7992_VAR_TYPE_44:
3739 default:
3840 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
153155
154156 dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
155157 memcpy(eeprom, fw->data, MT7996_EEPROM_SIZE);
156− dev->flash_mode = true;
158+ dev->eeprom_mode = EEPROM_MODE_DEFAULT_BIN;
157159
158160 out:
159161 release_firmware(fw);
@@ -163,26 +165,31 @@ out: · 3 unmodified lines
163165
164166 static int mt7996_eeprom_load(struct mt7996_dev *dev)
165167 {
168+ u32 eeprom_blk_size, block_num;
166169 bool use_default = false;
167− int ret;
170+ int ret, i;
168171
169172 ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
170173 if (ret < 0)
171174 return ret;
172175
173176 if (ret && !mt7996_check_eeprom(dev)) {
174− dev->flash_mode = true;
177+ dev->eeprom_mode = EEPROM_MODE_FLASH;
175178 goto out;
176179 }
177180
178− if (!dev->flash_mode) {
179− u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
180− u32 block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
181+ memset(dev->mt76.eeprom.data, 0, MT7996_EEPROM_SIZE);
182+ if (mt7996_has_ext_eeprom(dev)) {
183+ /* external eeprom mode */
184+ dev->eeprom_mode = EEPROM_MODE_EXT;
185+ eeprom_blk_size = MT7996_EXT_EEPROM_BLOCK_SIZE;
186+ } else {
181187 u8 free_block_num;
182− int i;
183188
184− memset(dev->mt76.eeprom.data, 0, MT7996_EEPROM_SIZE);
185− ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num);
189+ /* efuse mode */
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);
186193 if (ret < 0)
187194 return ret;
188195
@@ -191,27 +198,29 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev) · 2 unmodified lines
191198 use_default = true;
192199 goto out;
193200 }
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;
194215
195− /* check if eeprom data from fw is valid */
196− if (mt7996_mcu_get_eeprom(dev, 0, NULL, 0) ||
197− mt7996_check_eeprom(dev)) {
216+ if (i == block_num - 1)
217+ len = MT7996_EEPROM_SIZE % eeprom_blk_size;
218+ ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size,
219+ NULL, len, dev->eeprom_mode);
220+ if (ret && ret != -EINVAL) {
198221 use_default = true;
199222 goto out;
200223 }
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− }
215224 }
216225
217226 out:
@@ -385,7 +394,8 @@ bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev) · 167 unmodified lines
385394 return false;
386395 break;
387396 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)
389399 return false;
390400 break;
391401 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
3434 BIT(NL80211_CHAN_WIDTH_40) |
3535 BIT(NL80211_CHAN_WIDTH_80) |
3636 BIT(NL80211_CHAN_WIDTH_160),
37+ .beacon_int_min_gcd = 100,
38+};
39+
40+static 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,
3751 };
3852
3953 static const struct ieee80211_iface_limit if_limits[] = {
@@ -85,6 +99,7 @@ static const struct wiphy_iftype_ext_capab iftypes_ext_capa[] = { · 45 unmodified lines
8599 .extended_capabilities_mask = if_types_ext_capa_ap,
86100 .extended_capabilities_len = sizeof(if_types_ext_capa_ap),
87101 .mld_capa_and_ops =
102+ FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_FREQ_SEP_TYPE_IND, 1) |
88103 FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,
89104 MT7996_MAX_RADIOS - 1),
90105 },
@@ -485,7 +500,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) · 394 unmodified lines
485500 hw->vif_data_size = sizeof(struct mt7996_vif);
486501 hw->chanctx_data_size = sizeof(struct mt76_chanctx);
487502
488− wiphy->iface_combinations = &if_comb_global;
503+ wiphy->iface_combinations = is_mt7996(&dev->mt76) ? &if_comb_global :
504+ &if_comb_global_7992;
489505 wiphy->n_iface_combinations = 1;
490506
491507 wiphy->radio = dev->radios;
@@ -521,8 +537,10 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) · 29 unmodified lines
521537 ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
522538 ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
523539 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
540+ ieee80211_hw_set(hw, CHANCTX_STA_CSA);
524541
525542 hw->max_tx_fragments = 4;
543+ wiphy->txq_memory_limit = 32 << 20; /* 32 MiB */
526544
527545 /* init led callbacks */
528546 if (IS_ENABLED(CONFIG_MT76_LEDS)) {
@@ -592,7 +610,7 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev) · 63 unmodified lines
592610 void mt7996_mac_init(struct mt7996_dev *dev)
593611 {
594612 #define HIF_TXD_V2_1 0x21
595− int i;
613+ int i, rx_path_type;
596614
597615 mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
598616
@@ -606,11 +624,16 @@ void mt7996_mac_init(struct mt7996_dev *dev) · 7 unmodified lines
606624 }
607625
608626 /* 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;
610632 mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,
611− is_mt7996(&dev->mt76) ? 2 : 7);
612− else
633+ rx_path_type);
634+ } else {
613635 mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 0);
636+ }
614637
615638 if (mt7996_has_hwrro(dev)) {
616639 u16 timeout;
@@ -668,8 +691,9 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band) · 51 unmodified lines
668691 return 0;
669692
670693 if (dev->hif2 &&
671− ((is_mt7996(&dev->mt76) && band == MT_BAND2) ||
672− (is_mt7992(&dev->mt76) && band == MT_BAND1))) {
694+ ((is_mt7992(&dev->mt76) && band == MT_BAND1) ||
695+ (is_mt7996(&dev->mt76) && band == MT_BAND2 &&
696+ !mt76_npu_device_active(&dev->mt76)))) {
673697 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
674698 wed = &dev->mt76.mmio.wed_hif2;
675699 }
@@ -709,14 +733,19 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band) · 33 unmodified lines
709733 /* init wiphy according to mphy and phy */
710734 mt7996_init_wiphy_band(mphy->hw, phy);
711735
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)))) {
713739 int i;
714740
715741 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];
717743 } else {
718− ret = mt7996_init_tx_queues(mphy->priv, MT_TXQ_ID(band),
719− MT7996_TX_RING_SIZE,
744+ int size = is_mt7996(&dev->mt76) &&
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,
720749 MT_TXQ_RING_BASE(band) + hif1_ofs,
721750 wed);
722751 if (ret)
@@ -756,15 +785,41 @@ static void mt7996_init_work(struct work_struct *work) · 33 unmodified lines
756785 mt7996_mcu_set_eeprom(dev);
757786 mt7996_mac_init(dev);
758787 mt7996_txbf_init(dev);
788+
789+ if (!is_mt7990(&dev->mt76))
790+ mt7996_mcu_set_dup_wtbl(dev);
759791 }
760792
761793 void mt7996_wfsys_reset(struct mt7996_dev *dev)
762794 {
763− mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
764− msleep(20);
795+ if (!is_mt7990(&dev->mt76)) {
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;
765807
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);
767817 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");
768823 }
769824
770825 static 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
842897 }
843898 } else {
844899 /* set emul 3.0 function */
845− mt76_wr(dev, MT_RRO_3_0_EMU_CONF,
846− MT_RRO_3_0_EMU_CONF_EN_MASK);
900+ mt76_set(dev, MT_RRO_3_0_EMU_CONF, MT_RRO_3_0_EMU_CONF_EN_MASK);
847901
848902 mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE0,
849903 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
935989 addr++;
936990 }
937991
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+
938998 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
939999 if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
9401000 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
9951055 addr++;
9961056 }
9971057
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+
9981062 mt7996_rro_hw_init(dev);
9991063
10001064 return mt7996_dma_rro_init(dev);
@@ -1081,8 +1145,12 @@ static void mt7996_wed_rro_work(struct work_struct *work) · 80 unmodified lines
10811145 list);
10821146 list_del_init(&e->list);
10831147
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);
10851152 goto reset_session;
1153+ }
10861154
10871155 for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
10881156 void *ptr = dev->wed_rro.session.ptr;
@@ -1129,7 +1197,7 @@ static int mt7996_variant_type_init(struct mt7996_dev *dev) · 40 unmodified lines
11291197 else if (u32_get_bits(val, MT_PAD_GPIO_ADIE_COMB_7992))
11301198 var_type = MT7992_VAR_TYPE_44;
11311199 else
1132− return -EINVAL;
1200+ var_type = MT7992_VAR_TYPE_24;
11331201 break;
11341202 case MT7990_DEVICE_ID:
11351203 var_type = MT7990_VAR_TYPE_23;
@@ -1163,7 +1231,8 @@ static int mt7996_variant_fem_init(struct mt7996_dev *dev) · 27 unmodified lines
11631231 if (ret)
11641232 return ret;
11651233
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);
11671236 if (ret && ret != -EINVAL)
11681237 return ret;
11691238
@@ -1696,6 +1765,8 @@ int mt7996_register_device(struct mt7996_dev *dev) · 526 unmodified lines
16961765 if (ret)
16971766 return ret;
16981767
1768+ mt7996_dma_rro_start(dev);
1769+
16991770 ret = mt76_register_device(&dev->mt76, true, mt76_rates,
17001771 ARRAY_SIZE(mt76_rates));
17011772 if (ret)
@@ -1726,6 +1797,7 @@ error: · 24 unmodified lines
17261797
17271798 void mt7996_unregister_device(struct mt7996_dev *dev)
17281799 {
1800+ cancel_work_sync(&dev->dump_work);
17291801 cancel_work_sync(&dev->wed_rro.work);
17301802 mt7996_unregister_phy(mt7996_phy3(dev));
17311803 mt7996_unregister_phy(mt7996_phy2(dev));
drivers/net/wireless/mediatek/mt76/mt7996/mac.c+50−111
@@ -13,45 +13,6 @@ · 12 unmodified lines
1313
1414 #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
1515
16−static 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−
30−static 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−
41−static 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−
5516 static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
5617 u16 idx, u8 band_idx)
5718 {
@@ -527,7 +488,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, · 469 unmodified lines
527488 !(csum_status & (BIT(0) | BIT(2) | BIT(3))))
528489 skb->ip_summed = CHECKSUM_UNNECESSARY;
529490
530− if (rxd1 & MT_RXD3_NORMAL_FCS_ERR)
491+ if (rxd3 & MT_RXD3_NORMAL_FCS_ERR)
531492 status->flag |= RX_FLAG_FAILED_FCS_CRC;
532493
533494 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
700661
701662 hdr = mt76_skb_get_hdr(skb);
702663 fc = hdr->frame_control;
664+ if (ieee80211_is_beacon(fc))
665+ mt76_rx_beacon(mphy, skb);
703666 if (ieee80211_is_data_qos(fc)) {
704667 u8 *qos = ieee80211_get_qos_ctl(hdr);
705668
@@ -1139,10 +1102,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 433 unmodified lines
11391102 * req
11401103 */
11411104 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);
11431106
11441107 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);
11461109
11471110 val = FIELD_PREP(MT_TXP0_TOKEN_ID0, id) |
11481111 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
11611124 tx_info->buf[1].addr >> 32);
11621125 #endif
11631126 ptr[3] = cpu_to_le32(val);
1127+
1128+ tx_info->buf[0].len = MT_TXD_SIZE + mac_txp_size;
11641129 } else {
11651130 struct mt76_connac_txp_common *txp;
11661131
@@ -1270,8 +1235,9 @@ mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta, · 103 unmodified lines
12701235 if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
12711236 return;
12721237
1273− if (!test_and_set_bit(tid, &wcid->ampdu_state))
1274− ieee80211_start_tx_ba_session(link_sta->sta, tid, 0);
1238+ if (!test_and_set_bit(tid, &wcid->ampdu_state) &&
1239+ ieee80211_start_tx_ba_session(link_sta->sta, tid, 0))
1240+ clear_bit(tid, &wcid->ampdu_state);
12751241 }
12761242
12771243 static void
@@ -2203,9 +2169,14 @@ mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) · 925 unmodified lines
22032169
22042170 for_each_vif_active_link(vif, link_conf, link_id) {
22052171 struct mt7996_vif_link *link;
2172+ struct mt7996_phy *link_phy;
22062173
22072174 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)
22092180 continue;
22102181
22112182 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
22482219 }
22492220 spin_unlock_bh(&dev->mt76.token_lock);
22502221 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+ }
22512228 }
22522229
22532230 static int
@@ -2395,23 +2372,8 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta) · 141 unmodified lines
23952372 struct mt7996_dev *dev = data;
23962373 int i;
23972374
2398− for (i = 0; i < ARRAY_SIZE(msta->link); i++) {
2399− struct mt7996_sta_link *msta_link = NULL;
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− }
2375+ for (i = 0; i < ARRAY_SIZE(msta->link); i++)
2376+ mt7996_mac_sta_remove_link(dev, sta, i, true);
24152377 }
24162378
24172379 static void
@@ -2544,6 +2506,7 @@ void mt7996_mac_reset_work(struct work_struct *work) · 126 unmodified lines
25442506 if (mtk_wed_device_active(&dev->mt76.mmio.wed))
25452507 mtk_wed_device_stop(&dev->mt76.mmio.wed);
25462508
2509+ mt7996_npu_hw_stop(dev);
25472510 ieee80211_stop_queues(mt76_hw(dev));
25482511
25492512 set_bit(MT76_RESET, &dev->mphy.state);
@@ -2564,14 +2527,19 @@ void mt7996_mac_reset_work(struct work_struct *work) · 14 unmodified lines
25642527 mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
25652528 continue;
25662529
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+
25672537 napi_disable(&dev->mt76.napi[i]);
25682538 }
25692539 napi_disable(&dev->mt76.tx_napi);
25702540
25712541 mutex_lock(&dev->mt76.mutex);
25722542
2573− mt7996_npu_hw_stop(dev);
2574−
25752543 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
25762544
25772545 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
25912559 mt7996_dma_start(dev, false, false);
25922560
25932561 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);
25952563
25962564 if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
25972565 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
26102578 MT_INT_TX_RX_DONE_EXT);
26112579 }
26122580
2581+ __mt7996_npu_hw_init(dev);
2582+
26132583 clear_bit(MT76_MCU_RESET, &dev->mphy.state);
26142584 mt7996_for_each_phy(dev, phy)
26152585 clear_bit(MT76_RESET, &phy->mt76->state);
@@ -2619,6 +2589,13 @@ void mt7996_mac_reset_work(struct work_struct *work) · 3 unmodified lines
26192589 mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
26202590 continue;
26212591
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+
26222599 napi_enable(&dev->mt76.napi[i]);
26232600 local_bh_disable();
26242601 napi_schedule(&dev->mt76.napi[i]);
@@ -2639,8 +2616,6 @@ void mt7996_mac_reset_work(struct work_struct *work) · 14 unmodified lines
26392616
26402617 mutex_unlock(&dev->mt76.mutex);
26412618
2642− mt7996_npu_hw_init(dev);
2643−
26442619 mt7996_for_each_phy(dev, phy)
26452620 ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
26462621 MT7996_WATCHDOG_TIME);
@@ -2737,6 +2712,11 @@ void mt7996_reset(struct mt7996_dev *dev) · 90 unmodified lines
27372712 return;
27382713 }
27392714
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+
27402720 queue_work(dev->mt76.wq, &dev->reset_work);
27412721 wake_up(&dev->reset_wait);
27422722 }
@@ -2955,6 +2935,7 @@ void mt7996_mac_work(struct work_struct *work) · 212 unmodified lines
29552935
29562936 mutex_unlock(&mphy->dev->mutex);
29572937
2938+ mt76_beacon_mon_check(mphy);
29582939 mt76_tx_status_check(mphy->dev, false);
29592940
29602941 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
29742955
29752956 static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)
29762957 {
2977− int err, region;
2958+ int region;
29782959
29792960 switch (dev->mt76.region) {
29802961 case NL80211_DFS_ETSI:
@@ -2989,11 +2970,7 @@ static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx) · 8 unmodified lines
29892970 break;
29902971 }
29912972
2992− err = 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);
2973+ return mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region);
29972974 }
29982975
29992976 static 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
30152992 return err;
30162993 }
30172994
3018−static int
3019−mt7996_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−
30522995 int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)
30532996 {
30542997 struct mt7996_dev *dev = phy->dev;
@@ -3068,10 +3011,6 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy) · 13 unmodified lines
30683011 goto stop;
30693012
30703013 if (prev_state <= MT_DFS_STATE_DISABLED) {
3071− err = mt7996_dfs_init_radar_specs(phy);
3072− if (err < 0)
3073− return err;
3074−
30753014 err = mt7996_dfs_start_radar_detector(phy);
30763015 if (err < 0)
30773016 return err;
drivers/net/wireless/mediatek/mt76/mt7996/mac.h+0−5
@@ -37,9 +37,4 @@ struct mt7996_dfs_pattern { · 36 unmodified lines
3737 u32 min_stgpr_diff;
3838 } __packed;
3939
40−struct mt7996_dfs_radar_spec {
41− struct mt7996_dfs_pulse pulse_th;
42− struct mt7996_dfs_pattern radar_pattern[16];
43−};
44−
4540 #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
5656
5757 mutex_lock(&dev->mt76.mutex);
5858 ret = mt7996_mcu_set_hdr_trans(dev, true);
59− if (!ret && is_mt7992(&dev->mt76)) {
59+ if (!ret && !is_mt7996(&dev->mt76)) {
6060 u8 queue = mt76_connac_lmac_mapping(IEEE80211_AC_VI);
6161
6262 ret = mt7996_mcu_cp_support(dev, queue);
@@ -79,6 +79,7 @@ static void mt7996_stop_phy(struct mt7996_phy *phy) · 16 unmodified lines
7979
8080 mutex_lock(&dev->mt76.mutex);
8181
82+ mt7996_mcu_rdd_resume_tx(phy);
8283 mt7996_mcu_set_radio_en(phy, false);
8384
8485 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
238239 link_conf = &vif->bss_conf;
239240
240241 if (cmd == SET_KEY && !sta && !link->mt76.cipher) {
242+ struct mt7996_phy *phy = mt7996_vif_link_phy(link);
243+
241244 link->mt76.cipher =
242245 mt76_connac_mcu_get_cipher(key->cipher);
243− mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
244− &link->mt76, msta_link, true);
246+ if (phy)
247+ mt7996_mcu_add_bss_info(phy, vif, link_conf,
248+ &link->mt76, msta_link, true);
245249 }
246250
247251 if (cmd == SET_KEY)
@@ -300,9 +304,16 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, · 52 unmodified lines
300304 .cmd = SET_KEY,
301305 .link_id = link_conf->link_id,
302306 };
303− struct mt76_txq *mtxq;
304307 int mld_idx, idx, ret;
305308
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+
306317 mlink->idx = __ffs64(~dev->mt76.vif_mask);
307318 if (mlink->idx >= mt7996_max_interface_num(dev))
308319 return -ENOSPC;
@@ -316,7 +327,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, · 7 unmodified lines
316327 return -ENOSPC;
317328
318329 link->mld_idx = mld_idx;
319− link->phy = phy;
320330 mlink->omac_idx = idx;
321331 mlink->band_idx = band_idx;
322332 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
343353 mt7996_mac_wtbl_update(dev, idx,
344354 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
345355
346− if (vif->txq) {
347− mtxq = (struct mt76_txq *)vif->txq->drv_priv;
348− mtxq->wcid = idx;
349− }
350−
351356 if (vif->type != NL80211_IFTYPE_AP &&
352357 (!mlink->omac_idx || mlink->omac_idx > 3))
353358 vif->offload_flags = 0;
@@ -370,56 +375,66 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, · 16 unmodified lines
370375
371376 ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);
372377
373− if (!mlink->wcid->offchannel &&
374− mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED)
375− mvif->mt76.deflink_id = link_conf->link_id;
378+ if (!mlink->wcid->offchannel) {
379+ if (vif->txq &&
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+ }
376400
377401 return 0;
378402 }
379403
380−void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
381− struct ieee80211_bss_conf *link_conf,
382− struct mt76_vif_link *mlink)
404+static void mt7996_vif_link_destroy(struct mt7996_phy *phy,
405+ struct mt7996_vif_link *link,
406+ struct ieee80211_vif *vif,
407+ struct ieee80211_bss_conf *link_conf)
383408 {
384− struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
385409 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
386410 struct mt7996_sta_link *msta_link = &link->msta_link;
387− struct mt7996_phy *phy = mphy->priv;
388− struct mt7996_dev *dev = phy->dev;
411+ unsigned int link_id = msta_link->wcid.link_id;
412+ struct mt76_vif_link *mlink = &link->mt76;
389413 struct mt7996_key_iter_data it = {
390414 .cmd = SET_KEY,
391− .link_id = link_conf->link_id,
415+ .link_id = link_id,
392416 };
417+ struct mt7996_dev *dev = phy->dev;
393418 int idx = msta_link->wcid.idx;
394419
420+ if (!link_conf)
421+ link_conf = &vif->bss_conf;
422+
395423 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);
397425
398426 mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
399427 CONN_STATE_DISCONNECT, false);
400428 mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, false);
401−
402429 mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false);
403430
404431 rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
405432
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−
420433 dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);
421434 dev->mld_idx_mask &= ~BIT_ULL(link->mld_idx);
422435 phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
436+ if (!mlink->wcid->offchannel)
437+ mvif->mt76.valid_links &= ~BIT(link_id);
423438
424439 spin_lock_bh(&dev->mt76.sta_poll_lock);
425440 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
427442 spin_unlock_bh(&dev->mt76.sta_poll_lock);
428443
429444 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+
453+void 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+ }
430497 }
431498
432499 static 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
472539
473540 mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx),
474541 MT_DMA_DCR0_RXD_G5_EN, enabled);
542+ mt76_rmw_field(dev, MT_MDP_DCR0,
543+ MT_MDP_DCR0_RX_HDR_TRANS_EN, !enabled);
475544 mt7996_phy_set_rxfilter(phy);
476545 mt7996_mcu_set_sniffer_mode(phy, enabled);
477546 }
@@ -530,10 +599,29 @@ static void mt7996_remove_iter(void *data, u8 *mac, struct ieee80211_vif *vif) · 52 unmodified lines
530599 static void mt7996_remove_interface(struct ieee80211_hw *hw,
531600 struct ieee80211_vif *vif)
532601 {
602+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
603+ unsigned long rem_links = mvif->mt76.valid_links;
533604 struct mt7996_dev *dev = mt7996_hw_dev(hw);
534605 struct mt7996_radio_data rdata = {};
606+ unsigned int link_id;
535607 int i;
536608
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+
537625 ieee80211_iterate_active_interfaces_mtx(hw, 0, mt7996_remove_iter,
538626 &rdata);
539627 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
811899
812900 for_each_vif_active_link(vif, link_conf, link_id) {
813901 struct mt7996_vif_link *link;
902+ struct mt7996_phy *phy;
814903
815904 link = mt7996_vif_link(dev, vif, link_id);
816905 if (!link)
817906 continue;
818907
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)
820917 continue;
821918
822− mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
919+ mt7996_mcu_add_bss_info(phy, vif, link_conf,
823920 &link->mt76, &link->msta_link,
824921 true);
825922 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
828925 }
829926 }
830927
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+
831942 mutex_unlock(&dev->mt76.mutex);
832943 }
833944
@@ -864,6 +975,10 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 30 unmodified lines
864975 !!(changed & BSS_CHANGED_BSSID));
865976 }
866977
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+
867982 if (changed & BSS_CHANGED_ERP_SLOT) {
868983 int slottime = info->use_short_slot ? 9 : 20;
869984
@@ -927,10 +1042,82 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw, · 57 unmodified lines
9271042 struct cfg80211_chan_def *chandef)
9281043 {
9291044 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;
9301048
9311049 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+
1077+static int
1078+mt7996_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+
1101+out:
9331102 mutex_unlock(&dev->mt76.mutex);
1103+
1104+ return ret;
1105+}
1106+
1107+static void
1108+mt7996_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+ }
9341121 }
9351122
9361123 static int
@@ -941,30 +1128,22 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev, · 4 unmodified lines
9411128 {
9421129 struct ieee80211_sta *sta = link_sta->sta;
9431130 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);
9451132 struct mt7996_sta_link *msta_link;
9461133 int idx;
9471134
1135+ if (!phy)
1136+ return -EINVAL;
1137+
9481138 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
9491139 if (idx < 0)
9501140 return -ENOSPC;
9511141
9521142 if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
953− int i;
954−
9551143 msta_link = &msta->deflink;
9561144 msta->deflink_id = link_id;
9571145 msta->seclink_id = msta->deflink_id;
958−
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− }
1146+ mt7996_sta_init_txq_wcid(sta, idx);
9681147 } else {
9691148 msta_link = kzalloc_obj(*msta_link);
9701149 if (!msta_link)
@@ -1000,9 +1179,17 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev, · 29 unmodified lines
10001179 return 0;
10011180 }
10021181
1003−void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
1004− struct mt7996_sta_link *msta_link)
1182+void mt7996_mac_sta_remove_link(struct mt7996_dev *dev,
1183+ struct ieee80211_sta *sta,
1184+ unsigned int link_id, bool flush)
10051185 {
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+
10061193 spin_lock_bh(&dev->mt76.sta_poll_lock);
10071194 if (!list_empty(&msta_link->wcid.poll_list))
10081195 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
10111198 spin_unlock_bh(&dev->mt76.sta_poll_lock);
10121199
10131200 mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
1014− mt76_wcid_mask_clear(dev->mt76.wcid_mask, msta_link->wcid.idx);
1015−}
1016−
1017−static void
1018−mt7996_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;
10241201
1025− for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
1026− struct mt7996_sta_link *msta_link = NULL;
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;
1202+ if (msta_link->wcid.link_valid) {
1203+ struct mt7996_phy *phy;
10341204
10351205 mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
10361206 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
10371207
1038− mt7996_mac_sta_deinit_link(dev, msta_link);
1039− link = mt7996_vif_link(dev, vif, link_id);
1040− if (!link)
1041− continue;
1208+ phy = __mt7996_phy(dev, msta_link->wcid.phy_idx);
1209+ if (phy)
1210+ phy->mt76->num_sta--;
10421211
1043− mphy = mt76_vif_link_phy(&link->mt76);
1044− if (!mphy)
1045− continue;
1046−
1047− mphy->num_sta--;
10481212 if (msta->deflink_id == link_id) {
10491213 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+ }
10511230 } else if (msta->seclink_id == link_id) {
1052− msta->seclink_id = IEEE80211_LINK_UNSPECIFIED;
1231+ msta->seclink_id = msta->deflink_id;
10531232 }
1233+ msta_link->wcid.link_valid = false;
1234+ }
10541235
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);
10561242 }
10571243 }
10581244
1245+static void
1246+mt7996_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+
10591256 static int
10601257 mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
10611258 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
10671264 for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
10681265 struct ieee80211_bss_conf *link_conf;
10691266 struct ieee80211_link_sta *link_sta;
1267+ struct mt7996_sta_link *msta_link;
10701268 struct mt7996_vif_link *link;
10711269 struct mt76_phy *mphy;
10721270
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;
10741274 continue;
1275+ }
10751276
10761277 link_conf = link_conf_dereference_protected(vif, link_id);
10771278 if (!link_conf) {
@@ -1108,7 +1309,7 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif, · 30 unmodified lines
11081309 return 0;
11091310
11101311 error_unlink:
1111− mt7996_mac_sta_remove_links(dev, vif, sta, new_links);
1312+ mt7996_mac_sta_remove_links(dev, vif, sta, new_links, true);
11121313
11131314 return err;
11141315 }
@@ -1125,7 +1326,7 @@ mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 10 unmodified lines
11251326
11261327 mutex_lock(&dev->mt76.mutex);
11271328
1128− mt7996_mac_sta_remove_links(dev, vif, sta, rem);
1329+ mt7996_mac_sta_remove_links(dev, vif, sta, rem, false);
11291330 ret = mt7996_mac_sta_add_links(dev, vif, sta, add);
11301331
11311332 mutex_unlock(&dev->mt76.mutex);
@@ -1234,10 +1435,12 @@ static void · 102 unmodified lines
12341435 mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,
12351436 struct ieee80211_sta *sta)
12361437 {
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;
12381440
12391441 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);
12411444 mutex_unlock(&dev->mt76.mutex);
12421445 }
12431446
@@ -1489,8 +1692,8 @@ mt7996_get_stats(struct ieee80211_hw *hw, · 245 unmodified lines
14891692
14901693 u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link)
14911694 {
1695+ struct mt7996_phy *phy = mt7996_vif_link_phy(link);
14921696 struct mt7996_dev *dev = mt7996_hw_dev(hw);
1493− struct mt7996_phy *phy = link->phy;
14941697 union {
14951698 u64 t64;
14961699 u32 t32[2];
@@ -1549,7 +1752,7 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 52 unmodified lines
15491752
15501753 n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
15511754 : link->mt76.omac_idx;
1552− phy = link->phy;
1755+ phy = mt7996_vif_link_phy(link);
15531756 if (!phy)
15541757 goto unlock;
15551758
@@ -1583,7 +1786,7 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 27 unmodified lines
15831786 if (!link)
15841787 goto unlock;
15851788
1586− phy = link->phy;
1789+ phy = mt7996_vif_link_phy(link);
15871790 if (!phy)
15881791 goto unlock;
15891792
@@ -1713,9 +1916,14 @@ static void mt7996_link_rate_ctrl_update(void *data, · 123 unmodified lines
17131916 struct mt7996_sta_link *msta_link)
17141917 {
17151918 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;
17171921 u32 *changed = data;
17181922
1923+ if (!phy)
1924+ return;
1925+
1926+ dev = phy->dev;
17191927 spin_lock_bh(&dev->mt76.sta_poll_lock);
17201928
17211929 msta_link->changed |= *changed;
@@ -2204,6 +2412,10 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw, · 482 unmodified lines
22042412 path->mtk_wdma.wdma_idx = wed->wdma_idx;
22052413 else
22062414 #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
22072419 path->mtk_wdma.wdma_idx = link->mt76.band_idx;
22082420 path->mtk_wdma.bss = link->mt76.idx;
22092421 path->mtk_wdma.queue = 0;
@@ -2275,6 +2487,21 @@ mt7996_reconfig_complete(struct ieee80211_hw *hw, · 65 unmodified lines
22752487 MT7996_WATCHDOG_TIME);
22762488 }
22772489
2490+static int
2491+mt7996_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+
22782505 const struct ieee80211_ops mt7996_ops = {
22792506 .add_chanctx = mt76_add_chanctx,
22802507 .remove_chanctx = mt76_remove_chanctx,
@@ -2306,6 +2533,7 @@ const struct ieee80211_ops mt7996_ops = { · 25 unmodified lines
23062533 .release_buffered_frames = mt76_release_buffered_frames,
23072534 .get_txpower = mt7996_get_txpower,
23082535 .channel_switch_beacon = mt7996_channel_switch_beacon,
2536+ .post_channel_switch = mt7996_post_channel_switch,
23092537 .get_stats = mt7996_get_stats,
23102538 .get_et_sset_count = mt7996_get_et_sset_count,
23112539 .get_et_stats = mt7996_get_et_stats,
@@ -2337,4 +2565,5 @@ const struct ieee80211_ops mt7996_ops = { · 25 unmodified lines
23372565 .change_vif_links = mt7996_change_vif_links,
23382566 .change_sta_links = mt7996_mac_sta_change_links,
23392567 .reconfig_complete = mt7996_reconfig_complete,
2568+ .set_eml_op_mode = mt7996_set_eml_op_mode,
23402569 };
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c+685−138
@@ -18,6 +18,9 @@ · 17 unmodified lines
1818 case MT7992_VAR_TYPE_23: \
1919 _fw = MT7992_##name##_23; \
2020 break; \
21+ case MT7992_VAR_TYPE_24: \
22+ _fw = MT7992_##name##_24; \
23+ break; \
2124 default: \
2225 _fw = MT7992_##name; \
2326 } \
@@ -125,9 +128,16 @@ mt7996_mcu_set_sta_he_mcs(struct ieee80211_link_sta *link_sta, · 101 unmodified lines
125128 struct mt7996_vif_link *link,
126129 __le16 *he_mcs, u16 mcs_map)
127130 {
131+ struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76);
128132 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;
130− const u16 *mask = link->bitrate_mask.control[band].he_mcs;
133+ enum nl80211_band band;
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;
131141
132142 for (nss = 0; nss < max_nss; nss++) {
133143 int mcs;
@@ -209,6 +219,7 @@ static int · 75 unmodified lines
209219 mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd,
210220 struct sk_buff *skb, int seq)
211221 {
222+ struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
212223 struct mt7996_mcu_rxd *rxd;
213224 struct mt7996_mcu_uni_event *event;
214225 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
217228 if (!skb) {
218229 dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
219230 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+
220239 return -ETIMEDOUT;
221240 }
222241
@@ -233,7 +252,7 @@ mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd, · 10 unmodified lines
233252 event = (struct mt7996_mcu_uni_event *)skb->data;
234253 ret = le32_to_cpu(event->status);
235254 /* skip invalid event */
236− if (mcu_cmd != event->cid)
255+ if (mcu_cmd != le16_to_cpu(event->cid))
237256 ret = -EAGAIN;
238257 } else {
239258 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
259278 mdev->mcu.timeout = 2 * HZ;
260279 return;
261280 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;
263283 return;
264284 default:
265285 break;
@@ -313,13 +333,12 @@ mt7996_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, · 47 unmodified lines
313333 uni_txd->pkt_type = MCU_PKT_ID;
314334 uni_txd->seq = seq;
315335
316− if (cmd & __MCU_CMD_FIELD_QUERY)
317− uni_txd->option = MCU_CMD_UNI_QUERY_ACK;
318− else
319− uni_txd->option = MCU_CMD_UNI_EXT_ACK;
336+ uni_txd->option = MCU_CMD_UNI;
337+ if (!(cmd & __MCU_CMD_FIELD_QUERY))
338+ uni_txd->option |= MCU_CMD_SET;
320339
321− if (mcu_cmd == MCU_UNI_CMD_SDO)
322− uni_txd->option &= ~MCU_CMD_ACK;
340+ if (wait_seq)
341+ uni_txd->option |= MCU_CMD_ACK;
323342
324343 if ((cmd & __MCU_CMD_FIELD_WA) && (cmd & __MCU_CMD_FIELD_WM))
325344 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
390409 sizeof(req), false);
391410 }
392411
412+struct mt7996_mcu_countdown_data {
413+ struct mt76_phy *mphy;
414+ u8 omac_idx;
415+};
416+
393417 static void
394418 mt7996_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
395419 {
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+
446+static void
447+mt7996_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+
475+static void
476+mt7996_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))
397492 return;
398493
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+ }
400523 }
401524
402525 static void
@@ -416,24 +539,32 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) · 13 unmodified lines
416539 break;
417540 case MT_RDD_IDX_BACKGROUND:
418541 if (!dev->rdd2_phy)
419− return;
542+ goto err;
420543 mphy = dev->rdd2_phy->mt76;
421544 break;
422545 default:
423− dev_err(dev->mt76.dev, "Unknown RDD idx %d\n", r->rdd_idx);
424− return;
546+ goto err;
425547 }
426548
427549 if (!mphy)
428− return;
550+ goto err;
429551
430− if (r->rdd_idx == MT_RDD_IDX_BACKGROUND)
552+ if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) {
431553 cfg80211_background_radar_event(mphy->hw->wiphy,
432554 &dev->rdd2_chandef,
433555 GFP_ATOMIC);
434− else
556+ } else {
557+ struct mt7996_phy *phy = mphy->priv;
558+
559+ phy->rdd_tx_paused = true;
435560 ieee80211_radar_detected(mphy->hw, NULL);
561+ }
436562 dev->hw_pattern++;
563+
564+ return;
565+
566+err:
567+ dev_err(dev->mt76.dev, "Invalid RDD idx %d\n", r->rdd_idx);
437568 }
438569
439570 static void
@@ -476,57 +607,6 @@ out: · 36 unmodified lines
476607 wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, len, data);
477608 }
478609
479−static void
480−mt7996_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−
488−static void
489−mt7996_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−
530610 static int
531611 mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rate)
532612 {
@@ -1170,6 +1250,123 @@ out: · 637 unmodified lines
11701250 MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
11711251 }
11721252
1253+int 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+
1269+int 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+
1315+int 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+
11731370 int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
11741371 struct ieee80211_bss_conf *link_conf)
11751372 {
@@ -1779,9 +1976,8 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 603 unmodified lines
17791976 #define EBF_MODE BIT(0)
17801977 #define IBF_MODE BIT(1)
17811978 #define BF_MAT_ORDER 4
1979+ struct mt7996_phy *phy = mt7996_vif_link_phy(link);
17821980 struct ieee80211_vif *vif = link_conf->vif;
1783− struct mt7996_phy *phy = link->phy;
1784− int tx_ant = hweight16(phy->mt76->chainmask) - 1;
17851981 struct sta_rec_bf *bf;
17861982 struct tlv *tlv;
17871983 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
17901986 {2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */
17911987 {3, 5, 6, 0} /* 4x1, 4x2, 4x3, 4x4 */
17921988 };
1989+ int tx_ant;
17931990 bool ebf;
17941991
1992+ if (!phy)
1993+ return;
1994+
17951995 if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
17961996 return;
17971997
@@ -1807,17 +2007,18 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 9 unmodified lines
18072007 * ht: iBF only, since mac80211 lacks of eBF support
18082008 */
18092009 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);
18112011 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);
18132013 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);
18152015 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);
18172017 else
18182018 return;
18192019
18202020 bf->bf_cap = ebf ? EBF_MODE : (dev->ibf ? IBF_MODE : 0);
2021+ tx_ant = hweight16(phy->mt76->chainmask) - 1;
18212022 if (is_mt7992(&dev->mt76) && tx_ant == 4)
18222023 bf->bf_cap |= IBF_MODE;
18232024
@@ -1849,11 +2050,14 @@ mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 25 unmodified lines
18492050 struct ieee80211_link_sta *link_sta,
18502051 struct mt7996_vif_link *link)
18512052 {
1852− struct mt7996_phy *phy = link->phy;
1853− int tx_ant = hweight8(phy->mt76->antenna_mask) - 1;
2053+ struct mt7996_phy *phy = mt7996_vif_link_phy(link);
18542054 struct sta_rec_bfee *bfee;
18552055 struct tlv *tlv;
18562056 u8 nrow = 0;
2057+ int tx_ant;
2058+
2059+ if (!phy)
2060+ return;
18572061
18582062 if (!(link_sta->vht_cap.vht_supported || link_sta->he_cap.has_he))
18592063 return;
@@ -1877,6 +2081,7 @@ mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb, · 17 unmodified lines
18772081 }
18782082
18792083 /* reply with identity matrix to avoid 2x2 BF negative gain */
2084+ tx_ant = hweight8(phy->mt76->antenna_mask) - 1;
18802085 bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);
18812086 }
18822087
@@ -2060,6 +2265,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct mt7996_sta *msta, · 177 unmodified lines
20602265 struct ieee80211_sta *sta;
20612266 int ret, nrates = 0, idx;
20622267 enum nl80211_band band;
2268+ struct mt76_phy *mphy;
20632269 bool has_he;
20642270
20652271 #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
20932299 if (!link_sta)
20942300 goto error_unlock;
20952301
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;
20972307 has_he = link_sta->he_cap.has_he;
20982308 mask = link->bitrate_mask;
20992309 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
21732383 struct mt7996_vif_link *link)
21742384 {
21752385 #define INIT_RCPI 180
2176− struct mt76_phy *mphy = link->phy->mt76;
2177− struct cfg80211_chan_def *chandef = &mphy->chandef;
2386+ struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76);
21782387 struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
21792388 u32 cap = link_sta->sta->wme ? STA_CAP_WMM : 0;
2180− enum nl80211_band band = chandef->chan->band;
2389+ struct cfg80211_chan_def *chandef;
21812390 struct sta_rec_ra_uni *ra;
2391+ enum nl80211_band band;
21822392 struct tlv *tlv;
2183− u32 supp_rate = link_sta->supp_rates[band];
2393+ u32 supp_rate;
2394+
2395+ if (!mphy)
2396+ return;
21842397
21852398 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
21862399 ra = (struct sta_rec_ra_uni *)tlv;
21872400
2401+ chandef = &mphy->chandef;
2402+ band = chandef->chan->band;
2403+ supp_rate = link_sta->supp_rates[band];
2404+
21882405 ra->valid = true;
21892406 ra->auto_rate = true;
21902407 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
23662583 sizeof(req), true);
23672584 }
23682585
2586+int 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+
2623+int 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+
23692652 static void
23702653 mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
23712654 struct ieee80211_vif *vif,
@@ -2529,6 +2812,53 @@ int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev, · 157 unmodified lines
25292812 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
25302813 }
25312814
2815+void 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+
25322862 static int
25332863 mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid,
25342864 struct sk_buff *skb,
@@ -2676,6 +3006,16 @@ mt7996_mcu_beacon_cntdwn(struct sk_buff *rskb, struct sk_buff *skb, · 141 unmodified lines
26763006
26773007 info = (struct bss_bcn_cntdwn_tlv *)tlv;
26783008 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+ }
26793019 }
26803020
26813021 static void
@@ -2768,6 +3108,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 86 unmodified lines
27683108 {
27693109 struct mt7996_dev *dev = mt7996_hw_dev(hw);
27703110 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;
27713112 struct mt76_vif_link *mlink = link ? &link->mt76 : NULL;
27723113 struct ieee80211_mutable_offsets offs;
27733114 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
27823123 if (!mlink)
27833124 return -EINVAL;
27843125
2785− if (link->phy && link->phy->mt76->offchannel)
3126+ if (mphy && mphy->offchannel)
27863127 enabled = false;
27873128
27883129 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
28333174 {
28343175 #define OFFLOAD_TX_MODE_SU BIT(0)
28353176 #define OFFLOAD_TX_MODE_MU BIT(1)
3177+ struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76);
28363178 struct ieee80211_vif *vif = link_conf->vif;
28373179 struct ieee80211_hw *hw = mt76_hw(dev);
2838− struct mt7996_phy *phy = link->phy;
28393180 struct mt76_wcid *wcid = &dev->mt76.global_wcid;
28403181 struct bss_inband_discovery_tlv *discov;
28413182 struct ieee80211_tx_info *info;
@@ -2846,10 +3187,10 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, · 4 unmodified lines
28463187 u8 *buf, interval;
28473188 int len;
28483189
2849− if (!phy)
3190+ if (!mphy)
28503191 return -EINVAL;
28513192
2852− chandef = &phy->mt76->chandef;
3193+ chandef = &mphy->chandef;
28533194 band = chandef->chan->band;
28543195
28553196 if (link_conf->nontransmitted)
@@ -2887,7 +3228,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, · 31 unmodified lines
28873228 info = IEEE80211_SKB_CB(skb);
28883229 info->control.vif = vif;
28893230 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);
28913232
28923233 len = ALIGN(sizeof(*discov) + MT_TXD_SIZE + skb->len, 4);
28933234 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
37424083
37434084 if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
37444085 req.switch_reason = CH_SWITCH_NORMAL;
3745− else if (phy->mt76->offchannel ||
3746− phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
4086+ else if (phy->mt76->offchannel || !phy->mt76->chanctx)
37474087 req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
37484088 else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
37494089 NL80211_IFTYPE_AP))
@@ -3764,23 +4104,173 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag) · 14 unmodified lines
37644104 &req, sizeof(req), true);
37654105 }
37664106
3767−static int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev)
4107+static int
4108+mt7996_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+
4253+int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
37684254 {
37694255 #define MAX_PAGE_IDX_MASK GENMASK(7, 5)
37704256 #define PAGE_IDX_MASK GENMASK(4, 2)
37714257 #define PER_PAGE_SIZE 0x400
3772− struct mt7996_mcu_eeprom req = {
4258+ struct mt7996_mcu_eeprom_update req = {
37734259 .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),
37744260 .buffer_mode = EE_MODE_BUFFER
37754261 };
37764262 u16 eeprom_size = MT7996_EEPROM_SIZE;
37774263 u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE);
37784264 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;
37804270
37814271 for (i = 0; i < total; i++, eep += eep_len) {
37824272 struct sk_buff *skb;
3783− int ret, msg_len;
4273+ int msg_len;
37844274
37854275 if (i == total - 1 && !!(eeprom_size % PER_PAGE_SIZE))
37864276 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
38094299 return 0;
38104300 }
38114301
3812−int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
3813−{
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−
3828−int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len)
4302+int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
4303+ enum mt7996_eeprom_mode mode)
38294304 {
3830− struct {
3831− u8 _rsv[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)),
4305+ struct mt7996_mcu_eeprom_access req = {
4306+ .info.len = cpu_to_le16(sizeof(req) - 4),
38434307 };
4308+ struct mt7996_mcu_eeprom_access_event *event;
38444309 struct sk_buff *skb;
3845− bool valid;
3846− int ret;
4310+ int ret, cmd;
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+ }
38474328
3848− ret = mt76_mcu_send_and_get_msg(&dev->mt76,
3849− MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL),
3850− &req, sizeof(req), true, &skb);
4329+ req.info.addr = cpu_to_le32(addr);
4330+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, cmd, &req, sizeof(req),
4331+ true, &skb);
38514332 if (ret)
38524333 return ret;
38534334
3854− valid = le32_to_cpu(*(__le32 *)(skb->data + 16));
3855− if (valid) {
3856− u32 addr = le32_to_cpu(*(__le32 *)(skb->data + 12));
4335+ event = (struct mt7996_mcu_eeprom_access_event *)skb->data;
4336+ if (event->valid) {
4337+ u32 ret_len = le32_to_cpu(event->eeprom.ext_eeprom.data_len);
4338+
4339+ addr = le32_to_cpu(event->addr);
38574340
38584341 if (!buf)
38594342 buf = (u8 *)dev->mt76.eeprom.data + addr;
3860− if (!buf_len || buf_len > MT7996_EEPROM_BLOCK_SIZE)
3861− buf_len = MT7996_EEPROM_BLOCK_SIZE;
38624343
3863− skb_pull(skb, 48);
3864− memcpy(buf, skb->data, buf_len);
4344+ switch (mode) {
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+ }
38654362 } else {
38664363 ret = -EINVAL;
38674364 }
@@ -3871,7 +4368,7 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_l · 3 unmodified lines
38714368 return ret;
38724369 }
38734370
3874−int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
4371+int mt7996_mcu_get_efuse_free_block(struct mt7996_dev *dev, u8 *block_num)
38754372 {
38764373 struct {
38774374 u8 _rsv[4];
@@ -3903,7 +4400,6 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num) · 25 unmodified lines
39034400
39044401 int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)
39054402 {
3906−#define NIC_CAP 3
39074403 #define UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION 0x21
39084404 struct {
39094405 u8 _rsv[4];
@@ -3911,7 +4407,7 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap) · 1 unmodified line
39114407 __le16 tag;
39124408 __le16 len;
39134409 } __packed req = {
3914− .tag = cpu_to_le16(NIC_CAP),
4410+ .tag = cpu_to_le16(UNI_CHIP_CONFIG_NIC_CAPA),
39154411 .len = cpu_to_le16(sizeof(req) - 4),
39164412 };
39174413 struct sk_buff *skb;
@@ -4559,6 +5055,35 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable) · 641 unmodified lines
45595055 &req, sizeof(req), true);
45605056 }
45615057
5058+int 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+
45625087 int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val)
45635088 {
45645089 struct {
@@ -4889,3 +5414,25 @@ int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode) · 324 unmodified lines
48895414 return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(CP_SUPPORT),
48905415 &cp_mode, sizeof(cp_mode), true);
48915416 }
5417+
5418+int 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
2525 };
2626
2727 struct mt7996_mcu_uni_event {
28− u8 cid;
29− u8 __rsv[3];
28+ __le16 cid;
29+ u8 __rsv[2];
3030 __le32 status; /* 0: success, others: fail */
3131 } __packed;
3232
@@ -52,12 +52,10 @@ struct mt7996_mcu_thermal_enable { · 19 unmodified lines
5252 u8 rsv[2];
5353 } __packed;
5454
55−struct mt7996_mcu_csa_notify {
56− struct mt7996_mcu_rxd rxd;
57−
55+struct mt7996_mcu_countdown_notify {
5856 u8 omac_idx;
59− u8 csa_count;
60− u8 band_idx;
57+ u8 count;
58+ u8 csa_failure_reason; /* 0: success, 1: beacon disabled */
6159 u8 rsv;
6260 } __packed;
6361
@@ -147,7 +145,7 @@ struct mt7996_mcu_background_chain_ctrl { · 83 unmodified lines
147145 u8 rsv[2];
148146 } __packed;
149147
150−struct mt7996_mcu_eeprom {
148+struct mt7996_mcu_eeprom_update {
151149 u8 _rsv[4];
152150
153151 __le16 tag;
@@ -157,6 +155,43 @@ struct mt7996_mcu_eeprom { · 3 unmodified lines
157155 __le16 buf_len;
158156 } __packed;
159157
158+union 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+
166+struct mt7996_mcu_eeprom_info {
167+ u8 _rsv[4];
168+
169+ __le16 tag;
170+ __le16 len;
171+ __le32 addr;
172+ __le32 valid;
173+} __packed;
174+
175+struct mt7996_mcu_eeprom_access {
176+ struct mt7996_mcu_eeprom_info info;
177+ union eeprom_data eeprom;
178+} __packed;
179+
180+struct 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+
160195 struct mt7996_mcu_phy_rx_info {
161196 u8 category;
162197 u8 rate;
@@ -414,7 +449,16 @@ struct bss_bcn_cntdwn_tlv { · 251 unmodified lines
414449 __le16 tag;
415450 __le16 len;
416451 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;
418462 } __packed;
419463
420464 struct bss_bcn_mbss_tlv {
@@ -474,6 +518,24 @@ struct bss_mld_tlv { · 53 unmodified lines
474518 u8 __rsv[2];
475519 } __packed;
476520
521+struct bss_prot_tlv {
522+ __le16 tag;
523+ __le16 len;
524+ __le32 prot_mode;
525+} __packed;
526+
527+struct 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+
477539 struct sta_rec_ht_uni {
478540 __le16 tag;
479541 __le16 len;
@@ -647,6 +709,28 @@ struct mld_setup_link { · 167 unmodified lines
647709 u8 __rsv;
648710 } __packed;
649711
712+struct 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+
721+struct 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+
729+enum {
730+ UNI_CMD_MLD_RECONF_AP_REM_TIMER = 0x03,
731+ UNI_CMD_MLD_RECONF_STOP_LINK = 0x04,
732+};
733+
650734 struct hdr_trans_en {
651735 __le16 tag;
652736 __le16 len;
@@ -791,6 +875,11 @@ enum { · 138 unmodified lines
791875 UNI_CHANNEL_RX_PATH,
792876 };
793877
878+enum {
879+ UNI_CHIP_CONFIG_NIC_CAPA = 3,
880+ UNI_CHIP_CONFIG_DUP_WTBL = 4,
881+};
882+
794883 #define MT7996_BSS_UPDATE_MAX_SIZE (sizeof(struct bss_req_hdr) + \
795884 sizeof(struct mt76_connac_bss_basic_tlv) + \
796885 sizeof(struct bss_rlm_tlv) + \
@@ -837,6 +926,7 @@ enum { · 40 unmodified lines
837926 enum {
838927 UNI_BAND_CONFIG_RADIO_ENABLE,
839928 UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
929+ UNI_BAND_CONFIG_MAC_ENABLE_CTRL = 0x0c,
840930 };
841931
842932 enum {
@@ -856,6 +946,10 @@ enum { · 13 unmodified lines
856946 UNI_EFUSE_BUFFER_RD,
857947 };
858948
949+enum {
950+ UNI_EXT_EEPROM_ACCESS = 1,
951+};
952+
859953 enum {
860954 UNI_VOW_DRR_CTRL,
861955 UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h+63−7
@@ -29,6 +29,10 @@ · 28 unmodified lines
2929 #define MT7996_RX_RING_SIZE 1536
3030 #define MT7996_RX_MCU_RING_SIZE 512
3131 #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+
3236 /* scatter-gather of mcu event is not supported in connac3 */
3337 #define MT7996_RX_MCU_BUF_SIZE (2048 + \
3438 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
@@ -60,6 +64,11 @@ · 25 unmodified lines
6064 #define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"
6165 #define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"
6266
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+
6372 #define MT7990_FIRMWARE_WA ""
6473 #define MT7990_FIRMWARE_WM "mediatek/mt7996/mt7990_wm.bin"
6574 #define MT7990_FIRMWARE_DSP ""
@@ -75,12 +84,14 @@ · 9 unmodified lines
7584 #define MT7992_EEPROM_DEFAULT_MIX "mediatek/mt7996/mt7992_eeprom_2i5e.bin"
7685 #define MT7992_EEPROM_DEFAULT_23 "mediatek/mt7996/mt7992_eeprom_23.bin"
7786 #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"
7888
7989 #define MT7990_EEPROM_DEFAULT "mediatek/mt7996/mt7990_eeprom.bin"
8090 #define MT7990_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7990_eeprom_2i5i.bin"
8191
8292 #define MT7996_EEPROM_SIZE 7680
8393 #define MT7996_EEPROM_BLOCK_SIZE 16
94+#define MT7996_EXT_EEPROM_BLOCK_SIZE 1024
8495 #define MT7996_TOKEN_SIZE 16384
8596 #define MT7996_HW_TOKEN_SIZE 8192
8697
@@ -153,6 +164,7 @@ enum mt7996_var_type { · 66 unmodified lines
153164 enum mt7992_var_type {
154165 MT7992_VAR_TYPE_44,
155166 MT7992_VAR_TYPE_23,
167+ MT7992_VAR_TYPE_24,
156168 };
157169
158170 enum mt7990_var_type {
@@ -165,6 +177,18 @@ enum mt7996_fem_type { · 6 unmodified lines
165177 MT7996_FEM_MIX,
166178 };
167179
180+enum 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+
168192 enum mt7996_txq_id {
169193 MT7996_TXQ_FWDL = 16,
170194 MT7996_TXQ_MCU_WM,
@@ -252,8 +276,6 @@ struct mt7996_vif_link { · 81 unmodified lines
252276 struct mt76_vif_link mt76; /* must be first */
253277
254278 struct mt7996_sta_link msta_link;
255− struct mt7996_phy *phy;
256−
257279 struct cfg80211_bitrate_mask bitrate_mask;
258280
259281 u8 mld_idx;
@@ -377,6 +399,7 @@ struct mt7996_phy { · 117 unmodified lines
377399
378400 bool has_aux_rx;
379401 bool counter_reset;
402+ bool rdd_tx_paused;
380403 };
381404
382405 struct mt7996_dev {
@@ -436,7 +459,7 @@ struct mt7996_dev { · 53 unmodified lines
436459
437460 u32 hw_pattern;
438461
439− bool flash_mode:1;
462+ u8 eeprom_mode;
440463 bool has_eht:1;
441464
442465 struct {
@@ -473,6 +496,8 @@ struct mt7996_dev { · 30 unmodified lines
473496 struct list_head page_map[MT7996_RRO_MSDU_PG_HASH_SIZE];
474497 } wed_rro;
475498
499+ dma_addr_t npu_txd_addr[2 * MT7996_NPU_TXD_SIZE];
500+
476501 bool ibf;
477502 u8 fw_debug_wm;
478503 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
669694 struct ieee80211_bss_conf *link_conf,
670695 struct mt76_vif_link *mlink,
671696 struct mt7996_sta_link *msta_link, int enable);
697+int mt7996_mcu_update_bss_rfch(struct mt7996_phy *phy,
698+ struct mt7996_vif_link *link);
672699 int mt7996_mcu_add_sta(struct mt7996_dev *dev,
673700 struct ieee80211_bss_conf *link_conf,
674701 struct ieee80211_link_sta *link_sta,
@@ -678,6 +705,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, · 3 unmodified lines
678705 int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
679706 struct mt7996_vif_link *link,
680707 struct mt7996_sta_link *msta_link);
708+void mt7996_mcu_update_sta_rec_bw(void *data, struct ieee80211_sta *sta);
681709 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
682710 struct ieee80211_ampdu_params *params,
683711 struct ieee80211_vif *vif, bool enable);
@@ -707,8 +735,9 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, · 23 unmodified lines
707735 int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
708736 void *data, u8 link_id, u32 field);
709737 int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
710−int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
711−int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);
738+int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
739+ enum mt7996_eeprom_mode mode);
740+int mt7996_mcu_get_efuse_free_block(struct mt7996_dev *dev, u8 *block_num);
712741 int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap);
713742 int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band);
714743 int 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
719748 const struct mt7996_dfs_pattern *pattern);
720749 int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
721750 int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
751+int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *link,
752+ u8 ht_mode, bool use_cts_prot);
722753 int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
723754 struct ieee80211_bss_conf *link_conf);
724755 int 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
726757 int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
727758 int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
728759 int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
760+int mt7996_mcu_rdd_resume_tx(struct mt7996_phy *phy);
729761 int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val);
730762 int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
731763 struct cfg80211_chan_def *chandef);
@@ -743,6 +775,13 @@ void mt7996_mcu_exit(struct mt7996_dev *dev); · 11 unmodified lines
743775 int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
744776 int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
745777 int mt7996_mcu_set_sniffer_mode(struct mt7996_phy *phy, bool enabled);
778+int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev);
779+int mt7996_mcu_mld_reconf_stop_link(struct mt7996_dev *dev,
780+ struct ieee80211_vif *vif,
781+ u16 removed_links);
782+int mt7996_mcu_mld_link_oper(struct mt7996_dev *dev,
783+ struct ieee80211_bss_conf *link_conf,
784+ struct mt7996_vif_link *link, bool add);
746785
747786 static inline bool mt7996_has_hwrro(struct mt7996_dev *dev)
748787 {
@@ -802,6 +841,11 @@ static inline bool mt7996_has_wa(struct mt7996_dev *dev) · 53 unmodified lines
802841 return !is_mt7990(&dev->mt76);
803842 }
804843
844+static inline bool mt7996_has_ext_eeprom(struct mt7996_dev *dev)
845+{
846+ return !is_mt7996(&dev->mt76);
847+}
848+
805849 void mt7996_mac_init(struct mt7996_dev *dev);
806850 u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
807851 bool 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
823867 struct mt7996_vif_link *link,
824868 struct mt7996_sta_link *msta_link,
825869 u8 flowid);
826−void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
827− struct mt7996_sta_link *msta_link);
870+void mt7996_mac_sta_remove_link(struct mt7996_dev *dev,
871+ struct ieee80211_sta *sta,
872+ unsigned int link_id, bool flush);
828873 void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
829874 struct ieee80211_sta *sta,
830875 struct ieee80211_twt_setup *twt);
@@ -861,6 +906,10 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev, · 30 unmodified lines
861906 struct mt7996_vif_link *link,
862907 struct mt7996_sta_link *msta_link);
863908 int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
909+int 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);
864913 #ifdef CONFIG_MAC80211_DEBUGFS
865914 void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
866915 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
877926 #endif
878927
879928 int mt7996_dma_rro_init(struct mt7996_dev *dev);
929+void mt7996_dma_rro_start(struct mt7996_dev *dev);
880930
881931 #ifdef CONFIG_MT7996_NPU
932+int __mt7996_npu_hw_init(struct mt7996_dev *dev);
882933 int mt7996_npu_hw_init(struct mt7996_dev *dev);
883934 int mt7996_npu_hw_stop(struct mt7996_dev *dev);
884935 int mt7996_npu_rx_queues_init(struct mt7996_dev *dev);
885936 #else
937+static inline int __mt7996_npu_hw_init(struct mt7996_dev *dev)
938+{
939+ return 0;
940+}
941+
886942 static inline int mt7996_npu_hw_init(struct mt7996_dev *dev)
887943 {
888944 return 0;
drivers/net/wireless/mediatek/mt76/mt7996/npu.c+372−93
@@ -8,55 +8,20 @@ · 7 unmodified lines
88
99 #include "mt7996.h"
1010
11−static int mt7996_npu_offload_init(struct mt7996_dev *dev,
12− struct airoha_npu *npu)
11+static int mt7992_npu_txrx_offload_init(struct mt7996_dev *dev,
12+ struct airoha_npu *npu)
1313 {
14+ u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
1415 phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
15− u32 val, hif1_ofs = 0, dma_addr;
16+ u32 dma_addr;
1617 int i, err;
1718
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−
3919 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−
5520 err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_DESC,
5621 MT7996_RX_RING_SIZE, GFP_KERNEL);
5722 if (err) {
5823 dev_warn(dev->mt76.dev,
59− "failed setting NPU wlan PCIe desc size\n");
24+ "failed setting NPU wlan rx desc size\n");
6025 return err;
6126 }
6227
@@ -97,10 +62,173 @@ static int mt7996_npu_offload_init(struct mt7996_dev *dev, · 34 unmodified lines
9762 phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
9863 if (err) {
9964 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+
72+static 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");
101194 return err;
102195 }
103196
197+ return 0;
198+}
199+
200+static 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+
104232 err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE,
105233 MT7996_HW_TOKEN_SIZE, GFP_KERNEL);
106234 if (err)
@@ -111,7 +239,7 @@ static int mt7996_npu_offload_init(struct mt7996_dev *dev, · 4 unmodified lines
111239 return 0;
112240 }
113241
114−static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
242+static int mt7992_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
115243 {
116244 u32 val;
117245 int err;
@@ -120,7 +248,7 @@ static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu) · 2 unmodified lines
120248 &val, GFP_KERNEL);
121249 if (err) {
122250 dev_warn(dev->mt76.dev,
123− "failed retriving NPU wlan rx ring0 addr\n");
251+ "failed retrieving NPU wlan rx ring0 addr\n");
124252 return err;
125253 }
126254 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
129257 &val, GFP_KERNEL);
130258 if (err) {
131259 dev_warn(dev->mt76.dev,
132− "failed retriving NPU wlan rx ring1 addr\n");
260+ "failed retrieving NPU wlan rx ring1 addr\n");
133261 return err;
134262 }
135263 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
138266 &val, GFP_KERNEL);
139267 if (err) {
140268 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");
142270 return err;
143271 }
144272 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
146274 return 0;
147275 }
148276
277+static 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+
149341 static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
150342 {
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;
152348
153− for (i = MT_BAND0; i < MT_BAND2; i++) {
154− dma_addr_t dma_addr;
349+ BUILD_BUG_ON(ARRAY_SIZE(band_list) * 3 !=
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;
155354 u32 val;
156355
157− err = mt76_npu_get_msg(npu, i + 5,
356+ err = mt76_npu_get_msg(npu, band + 5,
158357 WLAN_FUNC_GET_WAIT_RXDESC_BASE,
159358 &val, GFP_KERNEL);
160359 if (err) {
161360 dev_warn(dev->mt76.dev,
162− "failed retriving NPU wlan tx ring addr\n");
361+ "failed retrieving NPU wlan tx ring addr\n");
163362 return err;
164363 }
165− writel(val, &dev->mt76.phys[i]->q_tx[0]->regs->desc_base);
166364
167− if (!dmam_alloc_coherent(dev->mt76.dma_dev,
168− 256 * MT7996_TX_RING_SIZE,
169− &dma_addr, GFP_KERNEL))
170− return -ENOMEM;
365+ phy_id = is_mt7996(&dev->mt76) ? band == MT_BAND0 ? 1 : 0
366+ : band;
367+ writel(val, &dev->mt76.phys[phy_id]->q_tx[0]->regs->desc_base);
171368
172− err = mt76_npu_send_msg(npu, i,
369+ err = mt76_npu_send_msg(npu, band,
173370 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
174− dma_addr, GFP_KERNEL);
371+ dev->npu_txd_addr[index++], GFP_KERNEL);
175372 if (err) {
176373 dev_warn(dev->mt76.dev,
177374 "failed setting NPU wlan queue buf addr\n");
178375 return err;
179376 }
180377
181− if (!dmam_alloc_coherent(dev->mt76.dma_dev,
182− 256 * MT7996_TX_RING_SIZE,
183− &dma_addr, GFP_KERNEL))
184− return -ENOMEM;
185−
186− err = mt76_npu_send_msg(npu, i + 5,
378+ err = mt76_npu_send_msg(npu, band + 5,
187379 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
188− dma_addr, GFP_KERNEL);
380+ dev->npu_txd_addr[index++],
381+ GFP_KERNEL);
189382 if (err) {
190383 dev_warn(dev->mt76.dev,
191384 "failed setting NPU wlan tx buf addr\n");
192385 return err;
193386 }
194387
195− if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024,
196− &dma_addr, GFP_KERNEL))
197− return -ENOMEM;
198−
199− err = mt76_npu_send_msg(npu, i + 10,
388+ err = mt76_npu_send_msg(npu, band + 10,
200389 WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
201− dma_addr, GFP_KERNEL);
390+ dev->npu_txd_addr[index++],
391+ GFP_KERNEL);
202392 if (err) {
203393 dev_warn(dev->mt76.dev,
204394 "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
212402 static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,
213403 struct airoha_npu *npu)
214404 {
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;
216406 phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
407+ struct mt76_queue *q = &dev->mt76.q_rx[qid];
217408 int err;
218409
219410 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
233424 return err;
234425 }
235426
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;
237429 err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
238430 phy_addr, GFP_KERNEL);
239431 if (err)
@@ -242,11 +434,54 @@ static int mt7996_npu_rx_event_init(struct mt7996_dev *dev, · 2 unmodified lines
242434 return err;
243435 }
244436
437+static 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+
245471 static int mt7996_npu_tx_done_init(struct mt7996_dev *dev,
246472 struct airoha_npu *npu)
247473 {
248474 int err;
249475
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+
250485 err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
251486 0, GFP_KERNEL);
252487 if (err) {
@@ -278,40 +513,79 @@ int mt7996_npu_rx_queues_init(struct mt7996_dev *dev) · 25 unmodified lines
278513 &dev->mt76.q_rx[MT_RXQ_NPU1]);
279514 }
280515
281−int mt7996_npu_hw_init(struct mt7996_dev *dev)
516+int __mt7996_npu_hw_init(struct mt7996_dev *dev)
282517 {
283518 struct airoha_npu *npu;
284− int i, err = 0;
285−
286− mutex_lock(&dev->mt76.mutex);
519+ int i, err;
287520
288521 npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
289522 if (!npu)
290− goto unlock;
523+ return 0;
291524
292525 err = mt7996_npu_offload_init(dev, npu);
293526 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);
295533
296− err = mt7996_npu_rxd_init(dev, npu);
297534 if (err)
298− goto unlock;
535+ return err;
299536
300537 err = mt7996_npu_txd_init(dev, npu);
301538 if (err)
302− goto unlock;
539+ return err;
303540
304541 err = mt7996_npu_rx_event_init(dev, npu);
305542 if (err)
306− goto unlock;
543+ return err;
544+
545+ err = mt7996_npu_set_pcie_addr(dev, npu);
546+ if (err)
547+ return err;
307548
308549 err = mt7996_npu_tx_done_init(dev, npu);
309550 if (err)
310− goto unlock;
551+ return err;
311552
312553 for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++)
313554 airoha_npu_wlan_enable_irq(npu, i - MT_RXQ_NPU0);
314−unlock:
555+
556+ return 0;
557+}
558+
559+int 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);
315589 mutex_unlock(&dev->mt76.mutex);
316590
317591 return err;
@@ -320,33 +594,38 @@ unlock: · 2 unmodified lines
320594 int mt7996_npu_hw_stop(struct mt7996_dev *dev)
321595 {
322596 struct airoha_npu *npu;
323− int i, err;
597+ int i, err = 0;
324598 u32 info;
325599
600+ mutex_lock(&dev->mt76.mutex);
601+
326602 npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
327603 if (!npu)
328− return 0;
604+ goto unlock;
329605
330606 err = mt76_npu_send_msg(npu, 4, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
331607 0, GFP_KERNEL);
332608 if (err)
333− return err;
609+ goto unlock;
334610
335611 for (i = 0; i < 10; i++) {
336612 err = mt76_npu_get_msg(npu, 3, WLAN_FUNC_GET_WAIT_NPU_INFO,
337613 &info, GFP_KERNEL);
338− if (err)
339− continue;
614+ if (!err && !info)
615+ break;
340616
341− if (info) {
342− err = -ETIMEDOUT;
343− continue;
344− }
617+ err = -ETIMEDOUT;
618+ usleep_range(10000, 15000);
345619 }
346620
347621 if (!err)
348622 err = mt76_npu_send_msg(npu, 6,
349623 WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
350624 0, GFP_KERNEL);
625+ else
626+ dev_err(dev->mt76.dev, "npu stop failed\n");
627+unlock:
628+ mutex_unlock(&dev->mt76.mutex);
629+
351630 return err;
352631 }
drivers/net/wireless/mediatek/mt76/mt7996/regs.h+11−0
@@ -159,6 +159,9 @@ enum offs_rev { · 158 unmodified lines
159159 #define MT_MDP_BASE 0x820cc000
160160 #define MT_MDP(ofs) (MT_MDP_BASE + (ofs))
161161
162+#define MT_MDP_DCR0 MT_MDP(0x800)
163+#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
164+
162165 #define MT_MDP_DCR2 MT_MDP(0x8e8)
163166 #define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2)
164167
@@ -733,7 +736,15 @@ enum offs_rev { · 568 unmodified lines
733736 #define MT_HW_REV 0x70010204
734737 #define MT_HW_REV1 0x8a00
735738
739+#define MT_WF_L05_RST 0x70028550
740+#define MT_WF_L05_RST_WF_RST_MASK GENMASK(4, 0)
741+
736742 #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)
737748
738749 /* PCIE MAC */
739750 #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
390390 }
391391 EXPORT_SYMBOL_GPL(mt76_npu_net_setup_tc);
392392
393+int 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+}
421+EXPORT_SYMBOL_GPL(mt76_npu_send_txrx_addr);
422+
393423 void mt76_npu_disable_irqs(struct mt76_dev *dev)
394424 {
395425 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
420450 struct airoha_npu *npu;
421451 int err = 0;
422452
423− /* NPU offloading is only supported by MT7992 */
424− if (!is_mt7992(dev))
425− return 0;
426−
427453 mutex_lock(&dev->mutex);
428454
429455 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
456482 dev->mmio.phy_addr = phy_addr;
457483 dev->mmio.npu_type = type;
458484 /* 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;
460487
461488 rcu_assign_pointer(dev->mmio.npu, npu);
462489 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
1616
1717 clear_bit(MT76_SCANNING, &phy->state);
1818
19− if (dev->scan.chan && phy->main_chandef.chan &&
20− !test_bit(MT76_MCU_RESET, &dev->phy.state))
19+ if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel &&
20+ !test_bit(MT76_MCU_RESET, &dev->phy.state)) {
2121 mt76_set_channel(phy, &phy->main_chandef, false);
22+ mt76_offchannel_notify(phy, false);
23+ }
2224 mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);
2325 memset(&dev->scan, 0, sizeof(dev->scan));
2426 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
2729
2830 void mt76_abort_scan(struct mt76_dev *dev)
2931 {
32+ spin_lock_bh(&dev->scan_lock);
33+ dev->scan.beacon_wait = false;
34+ spin_unlock_bh(&dev->scan_lock);
35+
3036 cancel_delayed_work_sync(&dev->scan_work);
3137 mt76_scan_complete(dev, true);
3238 }
@@ -77,6 +83,27 @@ out: · 44 unmodified lines
7783 rcu_read_unlock();
7884 }
7985
86+void 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+
103+out:
104+ spin_unlock(&dev->scan_lock);
105+}
106+
80107 void mt76_scan_work(struct work_struct *work)
81108 {
82109 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
85112 struct cfg80211_chan_def chandef = {};
86113 struct mt76_phy *phy = dev->scan.phy;
87114 int duration = HZ / 9; /* ~110 ms */
115+ bool beacon_rx, offchannel = true;
88116 int i;
89117
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+
90129 if (dev->scan.chan_idx >= req->n_channels) {
91130 mt76_scan_complete(dev, false);
92131 return;
93132 }
94133
95− if (dev->scan.chan && phy->num_sta) {
134+ if (dev->scan.chan && phy->num_sta && phy->offchannel) {
96135 dev->scan.chan = NULL;
97136 mt76_set_channel(phy, &phy->main_chandef, false);
137+ mt76_offchannel_notify(phy, false);
98138 goto out;
99139 }
100140
101141 dev->scan.chan = req->channels[dev->scan.chan_idx++];
102− cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20);
103− mt76_set_channel(phy, &chandef, true);
142+ offchannel = mt76_offchannel_chandef(phy, dev->scan.chan, &chandef);
143+
144+ if (offchannel)
145+ mt76_offchannel_notify(phy, true);
146+ mt76_set_channel(phy, &chandef, offchannel);
104147
105− if (!req->n_ssids ||
106− chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
148+ if (!req->n_ssids)
107149 goto out;
108150
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+
159+probe:
160+ if (phy->offchannel)
161+ duration = HZ / 16; /* ~60 ms */
110162 local_bh_disable();
111163 for (i = 0; i < req->n_ssids; i++)
112164 mt76_scan_send_probe(dev, &req->ssids[i]);
113165 local_bh_enable();
114166
115167 out:
116− if (dev->scan.chan)
168+ if (dev->scan.chan && phy->offchannel)
117169 duration = max_t(int, duration,
118170 msecs_to_jiffies(req->duration +
119171 (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
227227 struct sk_buff *skb)
228228 {
229229 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
230+ struct ieee80211_sta *sta;
230231 int pending;
232+ int i;
231233
232234 if (!wcid || info->tx_time_est)
233235 return;
@@ -235,6 +237,17 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid, · 1 unmodified line
235237 pending = atomic_dec_return(&wcid->non_aql_packets);
236238 if (pending < 0)
237239 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+ }
238251 }
239252
240253 void __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
542555 if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))
543556 continue;
544557
558+ if (atomic_read(&wcid->non_aql_packets) >= MT_MAX_NON_AQL_PKT)
559+ continue;
560+
545561 phy = mt76_dev_phy(dev, wcid->phy_idx);
546562 if (test_bit(MT76_RESET, &phy->state) || phy->offchannel)
547563 continue;
@@ -616,7 +632,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid, · 68 unmodified lines
616632
617633 if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
618634 !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
619− !ieee80211_is_data(hdr->frame_control) &&
635+ !ieee80211_is_data_present(hdr->frame_control) &&
620636 (!ieee80211_is_bufferable_mmpdu(skb) ||
621637 ieee80211_is_deauth(hdr->frame_control) ||
622638 head == &wcid->tx_offchannel))
@@ -644,7 +660,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid, · 21 unmodified lines
644660 return ret;
645661 }
646662
647−static void mt76_txq_schedule_pending(struct mt76_phy *phy)
663+void mt76_txq_schedule_pending(struct mt76_phy *phy)
648664 {
649665 LIST_HEAD(tx_list);
650666 int ret = 0;
@@ -850,9 +866,15 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi) · 199 unmodified lines
850866 token = idr_alloc(&dev->token, *ptxwi, dev->token_start,
851867 dev->token_start + dev->token_size,
852868 GFP_ATOMIC);
853− if (token >= dev->token_start)
869+ if (token >= dev->token_start) {
854870 dev->token_count++;
855871
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+
856878 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
857879 if (mtk_wed_device_active(&dev->mmio.wed) &&
858880 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
897919 if (txwi) {
898920 dev->token_count--;
899921
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+
900928 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
901929 if (mtk_wed_device_active(&dev->mmio.wed) &&
902930 token >= dev->mmio.wed.wlan.token_start &&
drivers/net/wireless/mediatek/mt7601u/mcu.c+14−1
@@ -403,12 +403,18 @@ error: · 402 unmodified lines
403403 return ret;
404404 }
405405
406+static const char * const mt7601u_fw_paths[] = {
407+ "mediatek/" MT7601U_FIRMWARE,
408+ MT7601U_FIRMWARE,
409+};
410+
406411 static int mt7601u_load_firmware(struct mt7601u_dev *dev)
407412 {
408413 const struct firmware *fw;
409414 const struct mt76_fw_header *hdr;
410415 int len, ret;
411416 u32 val;
417+ int i;
412418
413419 mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
414420 MT_USB_DMA_CFG_TX_BULK_EN));
@@ -416,7 +422,14 @@ static int mt7601u_load_firmware(struct mt7601u_dev *dev) · 1 unmodified line
416422 if (firmware_running(dev))
417423 return firmware_request_cache(dev->dev, MT7601U_FIRMWARE);
418424
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+
420433 if (ret)
421434 return ret;
422435
drivers/net/wireless/mediatek/mt7601u/usb.h+1−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include "mt7601u.h"
1010
1111 #define MT7601U_FIRMWARE "mt7601u.bin"
12+#define MT7601U_FIRMWARE_PATHS ARRAY_SIZE(mt7601u_fw_paths)
1213
1314 #define MT_VEND_REQ_MAX_RETRY 10
1415 #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
46404640 },
46414641 /* PPE threshold information is not supported */
46424642 },
4643+ .uhr_cap = {
4644+ .has_uhr = true,
4645+ .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
4646+ IEEE80211_UHR_PHY_CAP_ELR_TX,
4647+ },
46434648 },
46444649 {
46454650 .types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -4748,6 +4753,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = { · 102 unmodified lines
47484753 },
47494754 /* PPE threshold information is not supported */
47504755 },
4756+ .uhr_cap = {
4757+ .has_uhr = true,
4758+ .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
4759+ IEEE80211_UHR_PHY_CAP_ELR_TX,
4760+ },
47514761 },
47524762 #ifdef CONFIG_MAC80211_MESH
47534763 {
@@ -4917,6 +4927,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = { · 163 unmodified lines
49174927 },
49184928 /* PPE threshold information is not supported */
49194929 },
4930+ .uhr_cap = {
4931+ .has_uhr = true,
4932+ .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
4933+ IEEE80211_UHR_PHY_CAP_ELR_TX,
4934+ },
49204935 },
49214936 {
49224937 .types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -5042,6 +5057,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = { · 119 unmodified lines
50425057 },
50435058 /* PPE threshold information is not supported */
50445059 },
5060+ .uhr_cap = {
5061+ .has_uhr = true,
5062+ .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
5063+ IEEE80211_UHR_PHY_CAP_ELR_TX,
5064+ },
50455065 },
50465066 #ifdef CONFIG_MAC80211_MESH
50475067 {
@@ -5235,6 +5255,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = { · 187 unmodified lines
52355255 },
52365256 /* PPE threshold information is not supported */
52375257 },
5258+ .uhr_cap = {
5259+ .has_uhr = true,
5260+ .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
5261+ IEEE80211_UHR_PHY_CAP_ELR_TX,
5262+ },
52385263 },
52395264 {
52405265 .types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -5381,6 +5406,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = { · 140 unmodified lines
53815406 },
53825407 /* PPE threshold information is not supported */
53835408 },
5409+ .uhr_cap = {
5410+ .has_uhr = true,
5411+ .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
5412+ IEEE80211_UHR_PHY_CAP_ELR_TX,
5413+ },
53845414 },
53855415 #ifdef CONFIG_MAC80211_MESH
53865416 {
@@ -5472,6 +5502,11 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = { · 85 unmodified lines
54725502 },
54735503 /* PPE threshold information is not supported */
54745504 },
5505+ .uhr_cap = {
5506+ .has_uhr = true,
5507+ .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
5508+ IEEE80211_UHR_PHY_CAP_ELR_TX,
5509+ },
54755510 },
54765511 #endif
54775512 };
include/linux/ieee80211-nan.h+6−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
99 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
1010 * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
1111 * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
12− * Copyright (c) 2018 - 2025 Intel Corporation
12+ * Copyright (c) 2018 - 2026 Intel Corporation
1313 */
1414
1515 #ifndef LINUX_IEEE80211_NAN_H
@@ -23,6 +23,11 @@ · 7 unmodified lines
2323 #define NAN_OP_MODE_160MHZ 0x04
2424 #define NAN_OP_MODE_PNDL_SUPPRTED 0x08
2525
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+
2631 /* NAN Device capabilities, as defined in Wi-Fi Aware (TM) specification
2732 * Table 79
2833 */
include/linux/ieee80211.h+7−0
@@ -1194,6 +1194,13 @@ struct ieee80211_mgmt { · 1193 unmodified lines
11941194
11951195 #define IEEE80211_MIN_ACTION_SIZE(type) offsetofend(struct ieee80211_mgmt, u.action.type)
11961196
1197+/* Link Reconfiguration Status Duple field */
1198+struct ieee80211_ml_reconf_status {
1199+ u8 info;
1200+ __le16 status;
1201+} __packed;
1202+
1203+#define IEEE80211_ML_RECONF_LINK_ID_MASK 0xf
11971204
11981205 /* Management MIC information element (IEEE 802.11w) for CMAC */
11991206 struct ieee80211_mmie {
include/net/cfg80211.h+258−7
@@ -1831,6 +1831,7 @@ struct cfg80211_ttlm_params { · 1830 unmodified lines
18311831 * @eml_cap: EML capabilities of this station
18321832 * @link_sta_params: link related params.
18331833 * @epp_peer: EPP peer indication
1834+ * @nmi_mac: MAC address of the NMI station of the NAN peer
18341835 */
18351836 struct station_parameters {
18361837 struct net_device *vlan;
@@ -1858,6 +1859,7 @@ struct station_parameters { · 21 unmodified lines
18581859 u16 eml_cap;
18591860 struct link_station_parameters link_sta_params;
18601861 bool epp_peer;
1862+ const u8 *nmi_mac;
18611863 };
18621864
18631865 /**
@@ -1897,6 +1899,8 @@ struct station_del_parameters { · 33 unmodified lines
18971899 * entry that is operating, has been marked authorized by userspace)
18981900 * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed)
18991901 * @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
19001904 */
19011905 enum cfg80211_station_type {
19021906 CFG80211_STA_AP_CLIENT,
@@ -1908,6 +1912,8 @@ enum cfg80211_station_type { · 5 unmodified lines
19081912 CFG80211_STA_TDLS_PEER_ACTIVE,
19091913 CFG80211_STA_MESH_PEER_KERNEL,
19101914 CFG80211_STA_MESH_PEER_USER,
1915+ CFG80211_STA_NAN_MGMT,
1916+ CFG80211_STA_NAN_DATA,
19111917 };
19121918
19131919 /**
@@ -3980,6 +3986,77 @@ struct cfg80211_qos_map { · 2066 unmodified lines
39803986 struct cfg80211_dscp_range up[8];
39813987 };
39823988
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+
39834060 /**
39844061 * struct cfg80211_nan_band_config - NAN band specific configuration
39854062 *
@@ -4050,6 +4127,102 @@ struct cfg80211_nan_conf { · 64 unmodified lines
40504127 u16 vendor_elems_len;
40514128 };
40524129
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+ */
4143+struct 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+ */
4169+struct 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+ */
4188+struct 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+ */
4214+struct 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+
40534226 /**
40544227 * enum cfg80211_nan_conf_changes - indicates changed fields in NAN
40554228 * configuration
@@ -4830,6 +5003,19 @@ struct mgmt_frame_regs { · 774 unmodified lines
48305003 * @nan_change_conf: changes NAN configuration. The changed parameters must
48315004 * be specified in @changes (using &enum cfg80211_nan_conf_changes);
48325005 * 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.
48335019 *
48345020 * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
48355021 *
@@ -5207,7 +5393,12 @@ struct cfg80211_ops { · 371 unmodified lines
52075393 struct wireless_dev *wdev,
52085394 struct cfg80211_nan_conf *conf,
52095395 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);
52115402 int (*set_multicast_to_unicast)(struct wiphy *wiphy,
52125403 struct net_device *dev,
52135404 const bool enabled);
@@ -5836,6 +6027,12 @@ enum wiphy_nan_flags { · 622 unmodified lines
58366027 * @max_channel_switch_time: maximum channel switch time in milliseconds.
58376028 * @dev_capabilities: NAN device capabilities as defined in Wi-Fi Aware (TM)
58386029 * 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)
58396036 */
58406037 struct wiphy_nan_capa {
58416038 u32 flags;
@@ -5843,6 +6040,11 @@ struct wiphy_nan_capa { · 1 unmodified line
58436040 u8 n_antennas;
58446041 u16 max_channel_switch_time;
58456042 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;
58466048 };
58476049
58486050 #define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff
@@ -6736,8 +6938,8 @@ enum ieee80211_ap_reg_power { · 887 unmodified lines
67366938 * the P2P Device.
67376939 * @ps: powersave mode is enabled
67386940 * @ps_timeout: dynamic powersave timeout
6739− * @ap_unexpected_nlportid: (private) netlink port ID of application
6740− * registered for unexpected class 3 frames (AP mode)
6941+ * @unexpected_nlportid: (private) netlink port ID of application
6942+ * registered for unexpected frames (AP mode or NAN_DATA mode)
67416943 * @conn: (private) cfg80211 software SME connection state machine data
67426944 * @connect_keys: (private) keys to set after connection is established
67436945 * @conn_bss_type: connecting/connected BSS type
@@ -6799,7 +7001,7 @@ struct wireless_dev { · 55 unmodified lines
67997001 bool ps;
68007002 int ps_timeout;
68017003
6802− u32 ap_unexpected_nlportid;
7004+ u32 unexpected_nlportid;
68037005
68047006 u32 owner_nlportid;
68057007 bool nl_owner_dead;
@@ -6859,6 +7061,9 @@ struct wireless_dev { · 53 unmodified lines
68597061 } ocb;
68607062 struct {
68617063 u8 cluster_id[ETH_ALEN] __aligned(2);
7064+ u8 n_channels;
7065+ struct cfg80211_chan_def *chandefs;
7066+ bool sched_update_pending;
68627067 } nan;
68637068 } u;
68647069
@@ -9367,9 +9572,10 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, · 2502 unmodified lines
93679572 * @addr: the transmitter address
93689573 * @gfp: context flags
93699574 *
9370− * This function is used in AP mode (only!) to inform userspace that
9371− * a spurious class 3 frame was received, to be able to deauth the
9372− * sender.
9575+ * This function is used in AP mode to inform userspace that a spurious
9576+ * class 3 frame was received, to be able to deauth the 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.
93739579 * Return: %true if the frame was passed to userspace (or this failed
93749580 * for a reason other than not having a subscription.)
93759581 */
@@ -10016,6 +10222,18 @@ void cfg80211_nan_func_terminated(struct wireless_dev *wdev, · 640 unmodified lines
1001610222 enum nl80211_nan_func_term_reason reason,
1001710223 u64 cookie, gfp_t gfp);
1001810224
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+ */
10234+void cfg80211_nan_sched_update_done(struct wireless_dev *wdev, bool success,
10235+ gfp_t gfp);
10236+
1001910237 /* ethtool helper */
1002010238 void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
1002110239
@@ -10356,6 +10574,39 @@ void cfg80211_nan_cluster_joined(struct wireless_dev *wdev, · 334 unmodified lines
1035610574 const u8 *cluster_id, bool new_cluster,
1035710575 gfp_t gfp);
1035810576
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+ */
10588+void 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+ */
10606+void cfg80211_nan_channel_evac(struct wireless_dev *wdev,
10607+ const struct cfg80211_chan_def *chandef,
10608+ gfp_t gfp);
10609+
1035910610 #ifdef CONFIG_CFG80211_DEBUGFS
1036010611 /**
1036110612 * wiphy_locked_debugfs_read - do a locked read in debugfs
include/uapi/linux/nl80211.h+229−3
@@ -906,8 +906,9 @@ · 905 unmodified lines
906906 * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
907907 * (or GO) interface (i.e. hostapd) to ask for unexpected frames to
908908 * implement sending deauth to stations that send unexpected class 3
909− * frames. Also used as the event sent by the kernel when such a frame
910− * is received.
909+ * frames. For NAN_DATA interfaces, this is used to report frames from
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.
911912 * For the event, the %NL80211_ATTR_MAC attribute carries the TA and
912913 * other attributes like the interface index are present.
913914 * If used as the command it must have an interface index and you can
@@ -1367,6 +1368,53 @@ · 453 unmodified lines
13671368 * %NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP. The current channel
13681369 * definition is also sent.
13691370 *
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.
13701418 * @NL80211_CMD_MAX: highest used command number
13711419 * @__NL80211_CMD_AFTER_LAST: internal use
13721420 */
@@ -1632,6 +1680,16 @@ enum nl80211_commands { · 259 unmodified lines
16321680
16331681 NL80211_CMD_INCUMBENT_SIGNAL_DETECT,
16341682
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+
16351693 /* add new commands above here */
16361694
16371695 /* used to define NL80211_CMD_MAX below */
@@ -2659,7 +2717,8 @@ enum nl80211_commands { · 1021 unmodified lines
26592717 * a flow is assigned on each round of the DRR scheduler.
26602718 * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from
26612719 * 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).
26632722 *
26642723 * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include
26652724 * in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing
@@ -2991,6 +3050,82 @@ enum nl80211_commands { · 325 unmodified lines
29913050 * @NL80211_ATTR_DISABLE_UHR: Force UHR capable interfaces to disable
29923051 * this feature during association. This is a flag attribute.
29933052 * 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.
29943129 *
29953130 * @NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP: u32 attribute specifying
29963131 * the signal interference bitmap detected on the operating bandwidth for
@@ -3582,6 +3717,22 @@ enum nl80211_attrs { · 585 unmodified lines
35823717
35833718 NL80211_ATTR_UHR_OPERATION,
35843719
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+
35853736 /* add attributes here, update the policy in nl80211.c */
35863737
35873738 __NL80211_ATTR_AFTER_LAST,
@@ -3675,6 +3826,9 @@ enum nl80211_attrs { · 87 unmodified lines
36753826 * @NL80211_IFTYPE_OCB: Outside Context of a BSS
36763827 * This mode corresponds to the MIB variable dot11OCBActivated=true
36773828 * @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).
36783832 * @NL80211_IFTYPE_MAX: highest interface type number currently defined
36793833 * @NUM_NL80211_IFTYPES: number of defined interface types
36803834 *
@@ -3696,6 +3850,7 @@ enum nl80211_iftype { · 15 unmodified lines
36963850 NL80211_IFTYPE_P2P_DEVICE,
36973851 NL80211_IFTYPE_OCB,
36983852 NL80211_IFTYPE_NAN,
3853+ NL80211_IFTYPE_NAN_DATA,
36993854
37003855 /* keep last */
37013856 NUM_NL80211_IFTYPES,
@@ -4384,6 +4539,46 @@ enum nl80211_band_attr { · 682 unmodified lines
43844539
43854540 #define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
43864541
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+ */
4558+enum 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+
43874582 /**
43884583 * enum nl80211_wmm_rule - regulatory wmm rule
43894584 *
@@ -8557,6 +8752,8 @@ enum nl80211_s1g_short_beacon_attrs { · 4167 unmodified lines
85578752 * @NL80211_NAN_CAPA_CAPABILITIES: u8 attribute containing the
85588753 * capabilities of the device as defined in Wi-Fi Aware (TM)
85598754 * 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.
85608757 * @__NL80211_NAN_CAPABILITIES_LAST: Internal
85618758 * @NL80211_NAN_CAPABILITIES_MAX: Highest NAN capability attribute.
85628759 */
@@ -8569,9 +8766,38 @@ enum nl80211_nan_capabilities { · 6 unmodified lines
85698766 NL80211_NAN_CAPA_NUM_ANTENNAS,
85708767 NL80211_NAN_CAPA_MAX_CHANNEL_SWITCH_TIME,
85718768 NL80211_NAN_CAPA_CAPABILITIES,
8769+ NL80211_NAN_CAPA_PHY,
85728770 /* keep last */
85738771 __NL80211_NAN_CAPABILITIES_LAST,
85748772 NL80211_NAN_CAPABILITIES_MAX = __NL80211_NAN_CAPABILITIES_LAST - 1,
85758773 };
85768774
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+ */
8790+enum 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+
85778803 #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
718718 case NL80211_IFTYPE_P2P_CLIENT:
719719 case NL80211_IFTYPE_P2P_GO:
720720 case NL80211_IFTYPE_OCB:
721+ case NL80211_IFTYPE_NAN_DATA:
721722 /* shouldn't happen */
722723 WARN_ON_ONCE(1);
723724 break;
@@ -2140,12 +2141,13 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, · 1416 unmodified lines
21402141 return -EINVAL;
21412142
21422143 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,
21442145 params->ht_capa, link_sta);
21452146
21462147 /* VHT can override some HT caps such as the A-MSDU max length */
21472148 if (params->vht_capa)
21482149 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
2150+ &sband->vht_cap,
21492151 params->vht_capa, NULL,
21502152 link_sta);
21512153
net/mac80211/chan.c+123−76
@@ -166,6 +166,13 @@ int ieee80211_chanctx_refcount(struct ieee80211_local *local, · 165 unmodified lines
166166 for_each_chanctx_user_all(local, ctx, &iter)
167167 num++;
168168
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+
169176 return num;
170177 }
171178
@@ -447,74 +454,94 @@ ieee80211_get_max_required_bw(struct ieee80211_link_data *link) · 275 unmodified lines
447454 return max_bw;
448455 }
449456
457+static enum nl80211_chan_width
458+ieee80211_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+
450507 static enum nl80211_chan_width
451508 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
452509 struct ieee80211_chanctx *ctx,
453510 struct ieee80211_link_data *rsvd_for,
454511 bool check_reserved)
455512 {
456− struct ieee80211_sub_if_data *sdata;
457− struct ieee80211_link_data *link;
458513 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;
459517
460518 if (WARN_ON(check_reserved && rsvd_for))
461519 return ctx->conf.def.width;
462520
463− for_each_sdata_link(local, link) {
464− enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
465−
466− if (check_reserved) {
467− if (link->reserved_chanctx != ctx)
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);
521+ /* When this is true we only care about the reserving links */
522+ if (check_reserved) {
523+ for_each_chanctx_user_reserved(local, ctx, &iter) {
524+ width = ieee80211_get_width_of_link(iter.link);
525+ max_bw = max(max_bw, width);
513526 }
527+ goto check_monitor;
528+ }
514529
530+ /* Consider all assigned links */
531+ for_each_chanctx_user_assigned(local, ctx, &iter) {
532+ width = ieee80211_get_width_of_link(iter.link);
515533 max_bw = max(max_bw, width);
516534 }
517535
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+
544+check_monitor:
518545 /* use the configured bandwidth in case of monitor interface */
519546 sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
520547 if (sdata &&
@@ -752,10 +779,9 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local, · 231 unmodified lines
752779 _ieee80211_change_chanctx(local, ctx, old_ctx, chanreq, NULL);
753780 }
754781
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 */
756783 static struct ieee80211_chanctx *
757784 ieee80211_find_chanctx(struct ieee80211_local *local,
758− struct ieee80211_link_data *link,
759785 const struct ieee80211_chan_req *chanreq,
760786 enum ieee80211_chanctx_mode mode)
761787 {
@@ -767,9 +793,6 @@ ieee80211_find_chanctx(struct ieee80211_local *local, · 5 unmodified lines
767793 if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
768794 return NULL;
769795
770− if (WARN_ON(link->reserved_chanctx))
771− return NULL;
772−
773796 list_for_each_entry(ctx, &local->chanctx_list, list) {
774797 const struct ieee80211_chan_req *compat;
775798
@@ -790,12 +813,12 @@ ieee80211_find_chanctx(struct ieee80211_local *local, · 14 unmodified lines
790813 continue;
791814
792815 /*
793− * Reserve the chanctx temporarily, as the driver might change
816+ * Mark the chanctx as will be used, as the driver might change
794817 * active links during callbacks we make into it below and/or
795818 * later during assignment, which could (otherwise) cause the
796819 * context to actually be removed.
797820 */
798− link->reserved_chanctx = ctx;
821+ ctx->will_be_used = true;
799822
800823 ieee80211_change_chanctx(local, ctx, ctx, compat);
801824
@@ -1438,6 +1461,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link) · 636 unmodified lines
14381461 case NL80211_IFTYPE_P2P_GO:
14391462 case NL80211_IFTYPE_P2P_DEVICE:
14401463 case NL80211_IFTYPE_NAN:
1464+ case NL80211_IFTYPE_NAN_DATA:
14411465 case NUM_NL80211_IFTYPES:
14421466 WARN_ON(1);
14431467 break;
@@ -2011,6 +2035,36 @@ void __ieee80211_link_release_channel(struct ieee80211_link_data *link, · 567 unmodified lines
20112035 ieee80211_vif_use_reserved_switch(local);
20122036 }
20132037
2038+static struct ieee80211_chanctx *
2039+ieee80211_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+
20142068 int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
20152069 const struct ieee80211_chan_req *chanreq,
20162070 enum ieee80211_chanctx_mode mode,
@@ -2020,8 +2074,7 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, · 3 unmodified lines
20202074 struct ieee80211_local *local = sdata->local;
20212075 struct ieee80211_chanctx *ctx;
20222076 u8 radar_detect_width = 0;
2023− bool reserved = false;
2024− int radio_idx;
2077+ bool reused_ctx = false;
20252078 int ret;
20262079
20272080 lockdep_assert_wiphy(local->hw.wiphy);
@@ -2049,17 +2102,8 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, · 21 unmodified lines
20492102 if (!local->in_reconfig)
20502103 __ieee80211_link_release_channel(link, false);
20512104
2052− ctx = ieee80211_find_chanctx(local, link, chanreq, mode);
2053− /* Note: context is now reserved */
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);
2105+ ctx = ieee80211_find_or_create_chanctx(sdata, chanreq, mode,
2106+ assign_on_failure, &reused_ctx);
20632107 if (IS_ERR(ctx)) {
20642108 ret = PTR_ERR(ctx);
20652109 goto out;
@@ -2069,10 +2113,13 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, · 3 unmodified lines
20692113
20702114 ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);
20712115
2072− if (reserved) {
2073− /* remove reservation */
2074− WARN_ON(link->reserved_chanctx != ctx);
2075− link->reserved_chanctx = NULL;
2116+ /*
2117+ * In case an existing channel context is being used, we marked it as
2118+ * will_be_used, now that it is assigned - clear this indication
2119+ */
2120+ if (reused_ctx) {
2121+ WARN_ON(!ctx->will_be_used);
2122+ ctx->will_be_used = false;
20762123 }
20772124
20782125 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
108108 }
109109
110110 void
111−ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
112− struct ieee80211_supported_band *sband,
113− const u8 *he_cap_ie, u8 he_cap_len,
114− const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
115− struct link_sta_info *link_sta)
111+_ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
112+ const struct ieee80211_sta_he_cap *own_he_cap_ptr,
113+ const u8 *he_cap_ie, u8 he_cap_len,
114+ const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
115+ struct link_sta_info *link_sta)
116116 {
117117 struct ieee80211_sta_he_cap *he_cap = &link_sta->pub->he_cap;
118− const struct ieee80211_sta_he_cap *own_he_cap_ptr;
119118 struct ieee80211_sta_he_cap own_he_cap;
120119 struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie;
121120 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
125124
126125 memset(he_cap, 0, sizeof(*he_cap));
127126
128− if (!he_cap_ie)
129− return;
130−
131− own_he_cap_ptr =
132− ieee80211_get_he_iftype_cap_vif(sband, &sdata->vif);
133− if (!own_he_cap_ptr)
127+ if (!he_cap_ie || !own_he_cap_ptr || !own_he_cap_ptr->has_he)
134128 return;
135129
136130 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
164158 link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta);
165159 link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
166160
167− if (sband->band == NL80211_BAND_6GHZ && he_6ghz_capa)
161+ if (he_6ghz_capa)
168162 ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, link_sta);
169163
170164 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
207201 }
208202 }
209203
204+void
205+ieee80211_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+
210221 void
211222 ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,
212223 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
136136
137137
138138 bool 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,
140140 const struct ieee80211_ht_cap *ht_cap_ie,
141141 struct link_sta_info *link_sta)
142142 {
@@ -151,12 +151,12 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, · 8 unmodified lines
151151
152152 memset(&ht_cap, 0, sizeof(ht_cap));
153153
154− if (!ht_cap_ie || !sband->ht_cap.ht_supported)
154+ if (!ht_cap_ie || !own_cap_ptr->ht_supported)
155155 goto apply;
156156
157157 ht_cap.ht_supported = true;
158158
159− own_cap = sband->ht_cap;
159+ own_cap = *own_cap_ptr;
160160
161161 /*
162162 * 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
10141014 ieee80211_chandef_ht_oper(elems->ht_operation, &chandef);
10151015
10161016 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,
10181019 &htcap_ie,
10191020 &sta->deflink);
10201021
@@ -1033,6 +1034,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, · 12 unmodified lines
10331034 &chandef);
10341035 memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
10351036 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
1037+ &sband->vht_cap,
10361038 &cap_ie, NULL,
10371039 &sta->deflink);
10381040 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
928928
929929 bool radar_detected;
930930
931+ /* This chanctx is in process of getting used */
932+ bool will_be_used;
933+
931934 /* MUST be last - ends in a flexible-array member. */
932935 struct ieee80211_chanctx_conf conf;
933936 };
@@ -2185,7 +2188,7 @@ void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, · 1251 unmodified lines
21852188 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
21862189 struct ieee80211_sta_ht_cap *ht_cap);
21872190 bool 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,
21892192 const struct ieee80211_ht_cap *ht_cap_ie,
21902193 struct link_sta_info *link_sta);
21912194 void 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
22702273 void
22712274 ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
22722275 struct ieee80211_supported_band *sband,
2276+ const struct ieee80211_sta_vht_cap *own_vht_cap,
22732277 const struct ieee80211_vht_cap *vht_cap_ie,
22742278 const struct ieee80211_vht_cap *vht_cap_ie2,
22752279 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
23102314
23112315 /* HE */
23122316 void
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);
2322+void
23132323 ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
23142324 struct ieee80211_supported_band *sband,
23152325 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
12221222 }
12231223 }
12241224
1225− set_bit(SDATA_STATE_RUNNING, &sdata->state);
1226−
12271225 ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR);
12281226 if (ret) {
12291227 kfree(sdata);
12301228 return ret;
12311229 }
12321230
1231+ set_bit(SDATA_STATE_RUNNING, &sdata->state);
1232+
12331233 mutex_lock(&local->iflist_mtx);
12341234 rcu_assign_pointer(local->monitor_sdata, sdata);
12351235 mutex_unlock(&local->iflist_mtx);
@@ -1242,6 +1242,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local, · 6 unmodified lines
12421242 mutex_unlock(&local->iflist_mtx);
12431243 synchronize_net();
12441244 drv_remove_interface(local, sdata);
1245+ clear_bit(SDATA_STATE_RUNNING, &sdata->state);
12451246 kfree(sdata);
12461247 return ret;
12471248 }
@@ -1360,8 +1361,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 112 unmodified lines
13601361 break;
13611362 }
13621363 case NL80211_IFTYPE_AP:
1363− sdata->bss = &sdata->u.ap;
1364− break;
13651364 case NL80211_IFTYPE_MESH_POINT:
13661365 case NL80211_IFTYPE_STATION:
13671366 case NL80211_IFTYPE_MONITOR:
@@ -1369,6 +1368,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 1 unmodified line
13691368 case NL80211_IFTYPE_P2P_DEVICE:
13701369 case NL80211_IFTYPE_OCB:
13711370 case NL80211_IFTYPE_NAN:
1371+ case NL80211_IFTYPE_NAN_DATA:
13721372 /* no special treatment */
13731373 break;
13741374 case NL80211_IFTYPE_UNSPECIFIED:
@@ -1386,8 +1386,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 11 unmodified lines
13861386 local->reconfig_failure = false;
13871387
13881388 res = drv_start(local);
1389− if (res)
1390− goto err_del_bss;
1389+ if (res) {
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+ }
13911396 ieee80211_led_radio(local, true);
13921397 ieee80211_mod_tpt_led_trig(local,
13931398 IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
@@ -1458,6 +1463,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 64 unmodified lines
14581463 netif_carrier_on(dev);
14591464 list_add_tail_rcu(&sdata->u.mntr.list, &local->mon_list);
14601465 break;
1466+ case NL80211_IFTYPE_AP:
1467+ sdata->bss = &sdata->u.ap;
1468+ fallthrough;
14611469 default:
14621470 if (coming_up) {
14631471 ieee80211_del_virtual_monitor(local);
@@ -1546,12 +1554,10 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 82 unmodified lines
15461554 err_stop:
15471555 if (!local->open_count)
15481556 drv_stop(local, false);
1549− err_del_bss:
1550− sdata->bss = NULL;
15511557 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
15521558 list_del(&sdata->u.vlan.list);
1553− /* might already be clear but that doesn't matter */
1554− clear_bit(SDATA_STATE_RUNNING, &sdata->state);
1559+ /* Might not be initialized yet, but it is harmless */
1560+ sdata->bss = NULL;
15551561 return res;
15561562 }
15571563
@@ -1940,6 +1946,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, · 382 unmodified lines
19401946 case NL80211_IFTYPE_P2P_DEVICE:
19411947 sdata->vif.bss_conf.bssid = sdata->vif.addr;
19421948 break;
1949+ case NL80211_IFTYPE_NAN_DATA:
1950+ break;
19431951 case NL80211_IFTYPE_UNSPECIFIED:
19441952 case NL80211_IFTYPE_WDS:
19451953 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
450450 changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
451451 sta->sta.deflink.supp_rates[sband->band] = rates;
452452
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,
454454 elems->ht_cap_elem,
455455 &sta->deflink))
456456 changed |= IEEE80211_RC_BW_CHANGED;
457457
458458 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
459+ &sband->vht_cap,
459460 elems->vht_cap_elem, NULL,
460461 &sta->deflink);
461462
net/mac80211/mlme.c+10−7
@@ -5586,7 +5586,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, · 5585 unmodified lines
55865586
55875587 /* Set up internal HT/VHT capabilities */
55885588 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,
55905590 elems->ht_cap_elem,
55915591 link_sta);
55925592
@@ -5622,6 +5622,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, · 29 unmodified lines
56225622 }
56235623
56245624 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
5625+ &sband->vht_cap,
56255626 elems->vht_cap_elem,
56265627 bss_vht_cap, link_sta);
56275628 rcu_read_unlock();
@@ -10458,8 +10459,8 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata, · 4830 unmodified lines
1045810459 pos = mgmt->u.action.ml_reconf_resp.variable;
1045910460 len -= offsetofend(typeof(*mgmt), u.action.ml_reconf_resp);
1046010461
10461− /* each status duple is 3 octets */
10462− if (len < mgmt->u.action.ml_reconf_resp.count * 3) {
10462+ if (len < mgmt->u.action.ml_reconf_resp.count *
10463+ sizeof(struct ieee80211_ml_reconf_status)) {
1046310464 sdata_info(sdata,
1046410465 "mlo: reconf: unexpected len=%zu, count=%u\n",
1046510466 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
1046810469
1046910470 link_mask = sta_changed_links;
1047010471 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);
1047210474
10473− link_id = *pos;
10475+ link_id = u8_get_bits(reconf_status->info,
10476+ IEEE80211_ML_RECONF_LINK_ID_MASK);
1047410477
1047510478 if (!(link_mask & BIT(link_id))) {
1047610479 sdata_info(sdata,
@@ -10505,8 +10508,8 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata, · 28 unmodified lines
1050510508 sdata->u.mgd.reconf.added_links &= ~BIT(link_id);
1050610509 }
1050710510
10508− pos += 3;
10509− len -= 3;
10511+ pos += sizeof(*reconf_status);
10512+ len -= sizeof(*reconf_status);
1051010513 }
1051110514
1051210515 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
46074607 (ieee80211_is_public_action(hdr, skb->len) ||
46084608 (ieee80211_is_auth(hdr->frame_control) &&
46094609 ether_addr_equal(sdata->vif.addr, hdr->addr1)));
4610+ case NL80211_IFTYPE_NAN_DATA:
4611+ return false;
46104612 default:
46114613 break;
46124614 }
net/mac80211/trace.h+2−3
@@ -1778,9 +1778,8 @@ TRACE_EVENT(drv_switch_vif_chanctx, · 1777 unmodified lines
17781778 SWITCH_ENTRY_ASSIGN(vif.vif_type, vif->type);
17791779 SWITCH_ENTRY_ASSIGN(vif.p2p, vif->p2p);
17801780 SWITCH_ENTRY_ASSIGN(link_id, link_conf->link_id);
1781− strncpy(local_vifs[i].vif.vif_name,
1782− sdata->name,
1783− sizeof(local_vifs[i].vif.vif_name));
1781+ strscpy_pad(local_vifs[i].vif.vif_name,
1782+ sdata->name);
17841783 SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,
17851784 old_ctx->def.chan->center_freq);
17861785 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
21182118 return res;
21192119 }
21202120 break;
2121+ case NL80211_IFTYPE_NAN_DATA:
21212122 case NL80211_IFTYPE_AP_VLAN:
21222123 case NL80211_IFTYPE_MONITOR:
21232124 case NL80211_IFTYPE_P2P_DEVICE:
net/mac80211/vht.c+18−15
@@ -4,7 +4,7 @@ · 3 unmodified lines
44 *
55 * Portions of this file
66 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
7− * Copyright (C) 2018-2026 Intel Corporation
7+ * Copyright (C) 2018 - 2026 Intel Corporation
88 */
99
1010 #include <linux/ieee80211.h>
@@ -115,6 +115,7 @@ void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, · 104 unmodified lines
115115 void
116116 ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
117117 struct ieee80211_supported_band *sband,
118+ const struct ieee80211_sta_vht_cap *own_vht_cap,
118119 const struct ieee80211_vht_cap *vht_cap_ie,
119120 const struct ieee80211_vht_cap *vht_cap_ie2,
120121 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
122123 struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;
123124 struct ieee80211_sta_vht_cap own_cap;
124125 u32 cap_info, i;
125− bool have_80mhz;
126126 u32 mpdu_len;
127127
128128 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
130130 if (!link_sta->pub->ht_cap.ht_supported)
131131 return;
132132
133− if (!vht_cap_ie || !sband->vht_cap.vht_supported)
133+ if (!vht_cap_ie || !own_vht_cap->vht_supported)
134134 return;
135135
136− /* Allow VHT if at least one channel on the sband supports 80 MHz */
137− have_80mhz = false;
138− for (i = 0; i < sband->n_channels; i++) {
139− if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
140− IEEE80211_CHAN_NO_80MHZ))
141− continue;
136+ if (sband) {
137+ /* Allow VHT if at least one channel on the sband supports 80 MHz */
138+ bool have_80mhz = false;
142139
143− have_80mhz = true;
144− break;
145− }
140+ for (i = 0; i < sband->n_channels; i++) {
141+ if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
142+ IEEE80211_CHAN_NO_80MHZ))
143+ continue;
146144
147− if (!have_80mhz)
148− return;
145+ have_80mhz = true;
146+ break;
147+ }
148+
149+ if (!have_80mhz)
150+ return;
151+ }
149152
150153 /*
151154 * 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
156159
157160 vht_cap->vht_supported = true;
158161
159− own_cap = sband->vht_cap;
162+ own_cap = *own_vht_cap;
160163 /*
161164 * If user has specified capability overrides, take care
162165 * 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
317317 int step;
318318
319319 /* We only do strict verification on 6 GHz */
320− if (center < 5955 || center > 7115)
320+ if (center < 5955 || center > 7215)
321321 return true;
322322
323323 bw = nl80211_chan_width_to_mhz(width);
@@ -325,7 +325,7 @@ static bool cfg80211_valid_center_freq(u32 center, · 1 unmodified line
325325 return false;
326326
327327 /* 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)
329329 return false;
330330
331331 /* With 320 MHz the permitted channels overlap */
@@ -816,6 +816,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, · 484 unmodified lines
816816 case NL80211_IFTYPE_MONITOR:
817817 case NL80211_IFTYPE_AP_VLAN:
818818 case NL80211_IFTYPE_P2P_DEVICE:
819+ case NL80211_IFTYPE_NAN_DATA:
819820 break;
820821 case NL80211_IFTYPE_WDS:
821822 case NL80211_IFTYPE_UNSPECIFIED:
@@ -939,6 +940,7 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) · 117 unmodified lines
939940 case NL80211_IFTYPE_P2P_DEVICE:
940941 /* Can NAN type be considered as beaconing interface? */
941942 case NL80211_IFTYPE_NAN:
943+ case NL80211_IFTYPE_NAN_DATA:
942944 break;
943945 case NL80211_IFTYPE_UNSPECIFIED:
944946 case NL80211_IFTYPE_WDS:
net/wireless/core.c+120−10
@@ -5,7 +5,7 @@ · 4 unmodified lines
55 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
66 * Copyright 2013-2014 Intel Mobile Communications GmbH
77 * Copyright 2015-2017 Intel Deutschland GmbH
8− * Copyright (C) 2018-2025 Intel Corporation
8+ * Copyright (C) 2018-2026 Intel Corporation
99 */
1010
1111 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -254,6 +254,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, · 242 unmodified lines
254254 void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
255255 struct wireless_dev *wdev)
256256 {
257+ struct cfg80211_nan_local_sched empty_sched = {};
258+
257259 lockdep_assert_held(&rdev->wiphy.mtx);
258260
259261 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))
@@ -262,6 +264,15 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, · 2 unmodified lines
262264 if (!wdev_running(wdev))
263265 return;
264266
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+
265276 rdev_stop_nan(rdev, wdev);
266277 wdev->is_running = false;
267278
@@ -270,6 +281,47 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, · 2 unmodified lines
270281 rdev->opencount--;
271282 }
272283
284+int 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+
273325 void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
274326 {
275327 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -277,16 +329,21 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) · 1 unmodified line
277329
278330 ASSERT_RTNL();
279331
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+ */
280337 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
281338 if (wdev->netdev) {
282339 dev_close(wdev->netdev);
283340 continue;
284341 }
342+ }
285343
286− /* otherwise, check iftype */
287−
288− guard(wiphy)(wiphy);
344+ guard(wiphy)(wiphy);
289345
346+ list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
290347 switch (wdev->iftype) {
291348 case NL80211_IFTYPE_P2P_DEVICE:
292349 cfg80211_stop_p2p_device(rdev, wdev);
@@ -344,6 +401,8 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) · 51 unmodified lines
344401
345402 list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
346403 if (wdev->nl_owner_dead) {
404+ cfg80211_close_dependents(rdev, wdev);
405+
347406 if (wdev->netdev)
348407 dev_close(wdev->netdev);
349408
@@ -354,6 +413,21 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) · 4 unmodified lines
354413 }
355414 }
356415
416+void 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+
357431 static void cfg80211_destroy_iface_wk(struct work_struct *work)
358432 {
359433 struct cfg80211_registered_device *rdev;
@@ -761,6 +835,10 @@ int wiphy_register(struct wiphy *wiphy) · 401 unmodified lines
761835 !(wiphy->nan_supported_bands & BIT(NL80211_BAND_2GHZ)))))
762836 return -EINVAL;
763837
838+ if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN_DATA)) &&
839+ !wiphy->nan_capa.phy.ht.ht_supported))
840+ return -EINVAL;
841+
764842 if (WARN_ON(wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS)))
765843 return -EINVAL;
766844
@@ -1367,9 +1445,8 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, · 600 unmodified lines
13671445 rdev->num_running_monitor_ifaces += num;
13681446 }
13691447
1370−void cfg80211_leave(struct cfg80211_registered_device *rdev,
1371− struct wireless_dev *wdev,
1372− int link_id)
1448+void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
1449+ struct wireless_dev *wdev, int link_id)
13731450 {
13741451 struct net_device *dev = wdev->netdev;
13751452 struct cfg80211_sched_scan_request *pos, *tmp;
@@ -1420,6 +1497,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, · 44 unmodified lines
14201497 break;
14211498 case NL80211_IFTYPE_AP_VLAN:
14221499 case NL80211_IFTYPE_MONITOR:
1500+ case NL80211_IFTYPE_NAN_DATA:
14231501 /* nothing to do */
14241502 break;
14251503 case NL80211_IFTYPE_UNSPECIFIED:
@@ -1430,6 +1508,19 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, · 4 unmodified lines
14301508 }
14311509 }
14321510
1511+void 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+
14331524 void cfg80211_stop_link(struct wiphy *wiphy, struct wireless_dev *wdev,
14341525 int link_id, gfp_t gfp)
14351526 {
@@ -1445,6 +1536,9 @@ void cfg80211_stop_link(struct wiphy *wiphy, struct wireless_dev *wdev, · 9 unmodified lines
14451536
14461537 trace_cfg80211_stop_link(wiphy, wdev, link_id);
14471538
1539+ if (wdev->iftype == NL80211_IFTYPE_NAN)
1540+ return;
1541+
14481542 ev = kzalloc_obj(*ev, gfp);
14491543 if (!ev)
14501544 return;
@@ -1595,10 +1689,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 144 unmodified lines
15951689 }
15961690 break;
15971691 case NETDEV_GOING_DOWN:
1598− scoped_guard(wiphy, &rdev->wiphy) {
1599− cfg80211_leave(rdev, wdev, -1);
1692+ cfg80211_leave(rdev, wdev, -1);
1693+ scoped_guard(wiphy, &rdev->wiphy)
16001694 cfg80211_remove_links(wdev);
1601− }
16021695 /* since we just did cfg80211_leave() nothing to do there */
16031696 cancel_work_sync(&wdev->disconnect_wk);
16041697 cancel_work_sync(&wdev->pmsr_free_wk);
@@ -1679,6 +1772,23 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 74 unmodified lines
16791772
16801773 if (rfkill_blocked(rdev->wiphy.rfkill))
16811774 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+ }
16821792 break;
16831793 default:
16841794 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
318318
319319 void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
320320
321+void cfg80211_close_dependents(struct cfg80211_registered_device *rdev,
322+ struct wireless_dev *wdev);
323+
321324 /* free object */
322325 void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
323326
@@ -541,6 +544,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, · 217 unmodified lines
541544 void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
542545 enum nl80211_iftype iftype, int num);
543546
547+void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
548+ struct wireless_dev *wdev, int link_id);
549+
544550 void cfg80211_leave(struct cfg80211_registered_device *rdev,
545551 struct wireless_dev *wdev,
546552 int link_id);
@@ -551,6 +557,10 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, · 4 unmodified lines
551557 void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
552558 struct wireless_dev *wdev);
553559
560+int cfg80211_nan_set_local_schedule(struct cfg80211_registered_device *rdev,
561+ struct wireless_dev *wdev,
562+ struct cfg80211_nan_local_sched *sched);
563+
554564 struct cfg80211_internal_bss *
555565 cfg80211_bss_update(struct cfg80211_registered_device *rdev,
556566 struct cfg80211_internal_bss *tmp,
net/wireless/mlme.c+9−4
@@ -4,7 +4,7 @@ · 3 unmodified lines
44 *
55 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
66 * Copyright (c) 2015 Intel Deutschland GmbH
7− * Copyright (C) 2019-2020, 2022-2025 Intel Corporation
7+ * Copyright (C) 2019-2020, 2022-2026 Intel Corporation
88 */
99
1010 #include <linux/kernel.h>
@@ -782,8 +782,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 771 unmodified lines
782782 rdev_crit_proto_stop(rdev, wdev);
783783 }
784784
785− if (nlportid == wdev->ap_unexpected_nlportid)
786− wdev->ap_unexpected_nlportid = 0;
785+ if (nlportid == wdev->unexpected_nlportid)
786+ wdev->unexpected_nlportid = 0;
787787 }
788788
789789 void 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
933933 * cfg80211 doesn't track the stations
934934 */
935935 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;
936942 case NL80211_IFTYPE_P2P_DEVICE:
937943 /*
938944 * fall through, P2P device only supports
939945 * public action frames
940946 */
941− case NL80211_IFTYPE_NAN:
942947 default:
943948 err = -EOPNOTSUPP;
944949 break;
net/wireless/nl80211.c+877−28
@@ -333,6 +333,97 @@ static int validate_nan_cluster_id(const struct nlattr *attr, · 332 unmodified lines
333333 return 0;
334334 }
335335
336+static 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+
370+static 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+
336427 static int validate_uhr_capa(const struct nlattr *attr,
337428 struct netlink_ext_ack *extack)
338429 {
@@ -555,6 +646,13 @@ nl80211_nan_band_conf_policy[NL80211_NAN_BAND_CONF_ATTR_MAX + 1] = { · 216 unmodified lines
555646 [NL80211_NAN_BAND_CONF_DISABLE_SCAN] = { .type = NLA_FLAG },
556647 };
557648
649+static const struct nla_policy
650+nl80211_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+
558656 static const struct nla_policy
559657 nl80211_nan_conf_policy[NL80211_NAN_CONF_ATTR_MAX + 1] = {
560658 [NL80211_NAN_CONF_CLUSTER_ID] =
@@ -962,6 +1060,22 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 401 unmodified lines
9621060 [NL80211_ATTR_DISABLE_UHR] = { .type = NLA_FLAG },
9631061 [NL80211_ATTR_UHR_OPERATION] =
9641062 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),
9651079 };
9661080
9671081 /* policy for the key attributes */
@@ -1722,6 +1836,7 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) · 754 unmodified lines
17221836 return 0;
17231837 return -ENOLINK;
17241838 case NL80211_IFTYPE_NAN:
1839+ case NL80211_IFTYPE_NAN_DATA:
17251840 if (wiphy_ext_feature_isset(wdev->wiphy,
17261841 NL80211_EXT_FEATURE_SECURE_NAN))
17271842 return 0;
@@ -2678,6 +2793,68 @@ fail: · 950 unmodified lines
26782793 return -ENOBUFS;
26792794 }
26802795
2796+static 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+
2853+fail:
2854+ nla_nest_cancel(msg, nl_phy_cap);
2855+ return -ENOBUFS;
2856+}
2857+
26812858 static int nl80211_put_nan_capa(struct wiphy *wiphy, struct sk_buff *msg)
26822859 {
26832860 struct nlattr *nan_caps;
@@ -2704,6 +2881,9 @@ static int nl80211_put_nan_capa(struct wiphy *wiphy, struct sk_buff *msg) · 20 unmodified lines
27042881 wiphy->nan_capa.dev_capabilities))
27052882 goto fail;
27062883
2884+ if (nl80211_put_nan_phy_cap(wiphy, msg))
2885+ goto fail;
2886+
27072887 nla_nest_end(msg, nan_caps);
27082888
27092889 return 0;
@@ -4879,6 +5059,8 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) · 2169 unmodified lines
48795059 else
48805060 dev_close(wdev->netdev);
48815061
5062+ cfg80211_close_dependents(rdev, wdev);
5063+
48825064 mutex_lock(&rdev->wiphy.mtx);
48835065
48845066 return cfg80211_remove_virtual_intf(rdev, wdev);
@@ -7123,6 +7305,26 @@ static int parse_station_flags(struct genl_info *info, · 2238 unmodified lines
71237305 if ((params->sta_flags_mask |
71247306 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
71257307 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+
71267328 return 0;
71277329 }
71287330
@@ -8005,7 +8207,7 @@ static int nl80211_dump_station(struct sk_buff *skb, · 876 unmodified lines
80058207 /* nl80211_prepare_wdev_dump acquired it in the successful case */
80068208 __acquire(&rdev->wiphy.mtx);
80078209
8008− if (!wdev->netdev) {
8210+ if (!wdev->netdev && wdev->iftype != NL80211_IFTYPE_NAN) {
80098211 err = -EINVAL;
80108212 goto out_err;
80118213 }
@@ -8192,10 +8394,12 @@ int cfg80211_check_station_change(struct wiphy *wiphy, · 180 unmodified lines
81928394 return -EINVAL;
81938395 if (params->link_sta_params.supported_rates)
81948396 return -EINVAL;
8195− if (params->ext_capab || params->link_sta_params.ht_capa ||
8196− params->link_sta_params.vht_capa ||
8197− params->link_sta_params.he_capa ||
8198− params->link_sta_params.eht_capa ||
8397+ if (statype != CFG80211_STA_NAN_MGMT &&
8398+ (params->link_sta_params.ht_capa ||
8399+ params->link_sta_params.vht_capa ||
8400+ params->link_sta_params.he_capa))
8401+ return -EINVAL;
8402+ if (params->ext_capab || params->link_sta_params.eht_capa ||
81998403 params->link_sta_params.uhr_capa)
82008404 return -EINVAL;
82018405 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
82678471 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
82688472 return -EINVAL;
82698473 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;
82708487 }
82718488
82728489 /*
@@ -8481,7 +8698,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 208 unmodified lines
84818698
84828699 memset(&params, 0, sizeof(params));
84838700
8484− if (!dev)
8701+ if (!dev && wdev->iftype != NL80211_IFTYPE_NAN &&
8702+ wdev->iftype != NL80211_IFTYPE_NAN_DATA)
84858703 return -EINVAL;
84868704
84878705 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
86248842 case NL80211_IFTYPE_STATION:
86258843 case NL80211_IFTYPE_ADHOC:
86268844 case NL80211_IFTYPE_MESH_POINT:
8845+ case NL80211_IFTYPE_NAN:
8846+ case NL80211_IFTYPE_NAN_DATA:
86278847 break;
86288848 default:
86298849 err = -EOPNOTSUPP;
@@ -8652,7 +8872,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 22 unmodified lines
86528872
86538873 memset(&params, 0, sizeof(params));
86548874
8655− if (!dev)
8875+ if (!dev && wdev->iftype != NL80211_IFTYPE_NAN)
86568876 return -EINVAL;
86578877
86588878 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
86618881 if (!info->attrs[NL80211_ATTR_MAC])
86628882 return -EINVAL;
86638883
8664− if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
8665− return -EINVAL;
8884+ if (wdev->iftype == NL80211_IFTYPE_NAN ||
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;
86668891
8667− if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
8668− return -EINVAL;
8892+ /* Only NMI stations receive the HT/VHT/HE capabilities */
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;
86698901
8670− if (!info->attrs[NL80211_ATTR_STA_AID] &&
8671− !info->attrs[NL80211_ATTR_PEER_AID])
8672− return -EINVAL;
8902+ if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
8903+ return -EINVAL;
8904+
8905+ if (!info->attrs[NL80211_ATTR_STA_AID] &&
8906+ !info->attrs[NL80211_ATTR_PEER_AID])
8907+ return -EINVAL;
8908+ }
86738909
86748910 params.link_sta_params.link_id =
86758911 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
86858921 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
86868922 }
86878923
8688− params.link_sta_params.supported_rates =
8689− nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
8690− params.link_sta_params.supported_rates_len =
8691− nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
8692− params.listen_interval =
8693− nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
8924+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
8925+ params.link_sta_params.supported_rates =
8926+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
8927+ params.link_sta_params.supported_rates_len =
8928+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
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]);
86948934
86958935 if (info->attrs[NL80211_ATTR_VLAN_ID])
86968936 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
87098949
87108950 if (info->attrs[NL80211_ATTR_PEER_AID])
87118951 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
8712− else
8952+ else if (info->attrs[NL80211_ATTR_STA_AID])
87138953 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
87148954
87158955 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
88309070 return -EINVAL;
88319071 }
88329072
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+
88339083 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
88349084 if (params.link_sta_params.he_6ghz_capa &&
88359085 (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
89229172 */
89239173 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
89249174 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;
89259180 default:
89269181 return -EOPNOTSUPP;
89279182 }
@@ -8963,7 +9218,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) · 35 unmodified lines
89639218
89649219 memset(&params, 0, sizeof(params));
89659220
8966− if (!dev)
9221+ if (!dev && wdev->iftype != NL80211_IFTYPE_NAN)
89679222 return -EINVAL;
89689223
89699224 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
89749229 case NL80211_IFTYPE_AP_VLAN:
89759230 case NL80211_IFTYPE_MESH_POINT:
89769231 case NL80211_IFTYPE_P2P_GO:
9232+ case NL80211_IFTYPE_NAN:
9233+ case NL80211_IFTYPE_NAN_DATA:
89779234 /* always accept these */
89789235 break;
89799236 case NL80211_IFTYPE_ADHOC:
@@ -13950,6 +14207,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) · 4970 unmodified lines
1395014207 case NL80211_IFTYPE_P2P_DEVICE:
1395114208 break;
1395214209 case NL80211_IFTYPE_NAN:
14210+ case NL80211_IFTYPE_NAN_DATA:
1395314211 if (!wiphy_ext_feature_isset(wdev->wiphy,
1395414212 NL80211_EXT_FEATURE_SECURE_NAN) &&
1395514213 !(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
1401314271 case NL80211_IFTYPE_P2P_GO:
1401414272 break;
1401514273 case NL80211_IFTYPE_NAN:
14274+ case NL80211_IFTYPE_NAN_DATA:
1401614275 if (!wiphy_ext_feature_isset(wdev->wiphy,
1401714276 NL80211_EXT_FEATURE_SECURE_NAN) &&
1401814277 !(wdev->wiphy->nan_capa.flags &
@@ -15520,13 +15779,14 @@ static int nl80211_register_unexpected_frame(struct sk_buff *skb, · 1501 unmodified lines
1552015779 struct wireless_dev *wdev = dev->ieee80211_ptr;
1552115780
1552215781 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)
1552415784 return -EINVAL;
1552515785
15526− if (wdev->ap_unexpected_nlportid)
15786+ if (wdev->unexpected_nlportid)
1552715787 return -EBUSY;
1552815788
15529− wdev->ap_unexpected_nlportid = info->snd_portid;
15789+ wdev->unexpected_nlportid = info->snd_portid;
1553015790 return 0;
1553115791 }
1553215792
@@ -15922,6 +16182,10 @@ static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info) · 389 unmodified lines
1592216182 if (wdev->iftype != NL80211_IFTYPE_NAN)
1592316183 return -EOPNOTSUPP;
1592416184
16185+ cfg80211_close_dependents(rdev, wdev);
16186+
16187+ guard(wiphy)(&rdev->wiphy);
16188+
1592516189 cfg80211_stop_nan(rdev, wdev);
1592616190
1592716191 return 0;
@@ -16421,6 +16685,482 @@ nla_put_failure: · 493 unmodified lines
1642116685 }
1642216686 EXPORT_SYMBOL(cfg80211_nan_func_terminated);
1642316687
16688+void 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+
16728+nla_put_failure:
16729+ nlmsg_free(msg);
16730+}
16731+EXPORT_SYMBOL(cfg80211_nan_sched_update_done);
16732+
16733+static 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+
16814+static int
16815+nl80211_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+
16837+static int
16838+nl80211_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+
16864+static 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+
16921+static 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+
17070+static 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+
17083+static 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+
1642417164 static int nl80211_get_protocol_features(struct sk_buff *skb,
1642517165 struct genl_info *info)
1642617166 {
@@ -18096,7 +18836,11 @@ nl80211_epcs_cfg(struct sk_buff *skb, struct genl_info *info) · 1669 unmodified lines
1809618836 NL80211_FLAG_NEED_RTNL) \
1809718837 SELECTOR(__sel, WIPHY_CLEAR, \
1809818838 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)
1810018844
1810118845 enum nl80211_internal_flags_selector {
1810218846 #define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,
@@ -18933,6 +19677,7 @@ static const struct genl_small_ops nl80211_small_ops[] = { · 830 unmodified lines
1893319677 .doit = nl80211_stop_nan,
1893419678 .flags = GENL_ADMIN_PERM,
1893519679 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
19680+ NL80211_FLAG_NO_WIPHY_MTX |
1893619681 NL80211_FLAG_NEED_RTNL),
1893719682 },
1893819683 {
@@ -19227,6 +19972,18 @@ static const struct genl_small_ops nl80211_small_ops[] = { · 288 unmodified lines
1922719972 .flags = GENL_UNS_ADMIN_PERM,
1922819973 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1922919974 },
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+ },
1923019987 };
1923119988
1923219989 static 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
2052721284 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
2052821285 struct sk_buff *msg;
2052921286 void *hdr;
20530− u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
21287+ u32 nlportid = READ_ONCE(wdev->unexpected_nlportid);
2053121288
2053221289 if (!nlportid)
2053321290 return false;
@@ -20567,7 +21324,8 @@ bool cfg80211_rx_spurious_frame(struct net_device *dev, const u8 *addr, · 33 unmodified lines
2056721324 trace_cfg80211_rx_spurious_frame(dev, addr, link_id);
2056821325
2056921326 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)) {
2057121329 trace_cfg80211_return_bool(false);
2057221330 return false;
2057321331 }
@@ -22137,6 +22895,97 @@ void cfg80211_nan_cluster_joined(struct wireless_dev *wdev, · 1563 unmodified lines
2213722895 }
2213822896 EXPORT_SYMBOL(cfg80211_nan_cluster_joined);
2213922897
22898+void 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+}
22939+EXPORT_SYMBOL(cfg80211_nan_ulw_update);
22940+
22941+void 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+}
22987+EXPORT_SYMBOL(cfg80211_nan_channel_evac);
22988+
2214022989 /* initialisation/exit functions */
2214122990
2214222991 int __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
10601060 return ret;
10611061 }
10621062
1063+static inline int
1064+rdev_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+
1079+static inline int
1080+rdev_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+
10631095 static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
10641096 struct net_device *dev,
10651097 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
23482348 if (!wdev->netdev || !netif_running(wdev->netdev))
23492349 return true;
23502350
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+
23512363 for (link = 0; link < ARRAY_SIZE(wdev->links); link++) {
23522364 struct ieee80211_channel *chan;
23532365
@@ -2397,9 +2409,9 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) · 43 unmodified lines
23972409 continue;
23982410 chandef = wdev->u.ocb.chandef;
23992411 break;
2400− case NL80211_IFTYPE_NAN:
2401− /* we have no info, but NAN is also pretty universal */
2402− continue;
2412+ case NL80211_IFTYPE_NAN_DATA:
2413+ /* NAN channels are checked in NL80211_IFTYPE_NAN interface */
2414+ break;
24032415 default:
24042416 /* others not implemented for now */
24052417 WARN_ON_ONCE(1);
@@ -2436,11 +2448,14 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy) · 30 unmodified lines
24362448 struct wireless_dev *wdev;
24372449 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
24382450
2439− guard(wiphy)(wiphy);
2451+ list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
2452+ bool valid;
24402453
2441− list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
2442− if (!reg_wdev_chan_valid(wiphy, wdev))
2454+ scoped_guard(wiphy, wiphy)
2455+ valid = reg_wdev_chan_valid(wiphy, wdev);
2456+ if (!valid)
24432457 cfg80211_leave(rdev, wdev, -1);
2458+ }
24442459 }
24452460
24462461 static 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
102102 if (!rdev->wiphy.registered)
103103 goto out_unlock_rtnl;
104104
105− wiphy_lock(&rdev->wiphy);
106105 if (rdev->wiphy.wowlan_config) {
107− cfg80211_process_wiphy_works(rdev, NULL);
108− if (rdev->ops->suspend)
109− ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
110− if (ret <= 0)
111− goto out_unlock_wiphy;
106+ scoped_guard(wiphy, &rdev->wiphy) {
107+ cfg80211_process_wiphy_works(rdev, NULL);
108+ if (rdev->ops->suspend)
109+ ret = rdev_suspend(rdev,
110+ rdev->wiphy.wowlan_config);
111+ if (ret <= 0)
112+ goto out_unlock_rtnl;
113+ }
112114 }
113115
114116 /* Driver refused to configure wowlan (ret = 1) or no wowlan */
115117
116118 cfg80211_leave_all(rdev);
117− cfg80211_process_rdev_events(rdev);
118− cfg80211_process_wiphy_works(rdev, NULL);
119− if (rdev->ops->suspend)
120− ret = rdev_suspend(rdev, NULL);
121−
122−out_unlock_wiphy:
123− wiphy_unlock(&rdev->wiphy);
119+ scoped_guard(wiphy, &rdev->wiphy) {
120+ cfg80211_process_rdev_events(rdev);
121+ cfg80211_process_wiphy_works(rdev, NULL);
122+ if (rdev->ops->suspend)
123+ ret = rdev_suspend(rdev, NULL);
124+ }
124125 out_unlock_rtnl:
125126 if (ret == 0)
126127 rdev->suspended = true;
net/wireless/trace.h+105−0
@@ -2410,6 +2410,55 @@ TRACE_EVENT(rdev_del_nan_func, · 2409 unmodified lines
24102410 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
24112411 );
24122412
2413+TRACE_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+
2434+TRACE_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+
24132462 TRACE_EVENT(rdev_set_mac_acl,
24142463 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
24152464 struct cfg80211_acl_data *params),
@@ -4276,6 +4325,62 @@ TRACE_EVENT(cfg80211_incumbent_signal_notify, · 1860 unmodified lines
42764325 TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", signal_interference_bitmap=0x%x",
42774326 WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->signal_interference_bitmap)
42784327 );
4328+
4329+TRACE_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+
4346+TRACE_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+
4367+TRACE_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+);
42794384 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
42804385
42814386 #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
9090 /* see 802.11ax D6.1 27.3.23.2 */
9191 if (chan == 2)
9292 return MHZ_TO_KHZ(5935);
93− if (chan <= 233)
93+ if (chan <= 253)
9494 return MHZ_TO_KHZ(5950 + chan * 5);
9595 break;
9696 case NL80211_BAND_60GHZ:
@@ -625,8 +625,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, · 528 unmodified lines
625625 case cpu_to_le16(0):
626626 if (iftype != NL80211_IFTYPE_ADHOC &&
627627 iftype != NL80211_IFTYPE_STATION &&
628− iftype != NL80211_IFTYPE_OCB)
629− return -1;
628+ iftype != NL80211_IFTYPE_OCB &&
629+ iftype != NL80211_IFTYPE_NAN_DATA)
630+ return -1;
630631 break;
631632 }
632633
@@ -1144,8 +1145,15 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) · 511 unmodified lines
11441145 ev->ij.channel);
11451146 break;
11461147 case EVENT_STOPPED:
1147− cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev,
1148− ev->link_id);
1148+ /*
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);
11491157 break;
11501158 case EVENT_PORT_AUTHORIZED:
11511159 __cfg80211_port_authorized(wdev, ev->pa.peer_addr,
@@ -1184,6 +1192,13 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 32 unmodified lines
11841192 if (otype == NL80211_IFTYPE_AP_VLAN)
11851193 return -EOPNOTSUPP;
11861194
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+
11871202 /* cannot change into P2P device or NAN */
11881203 if (ntype == NL80211_IFTYPE_P2P_DEVICE ||
11891204 ntype == NL80211_IFTYPE_NAN)
@@ -1204,7 +1219,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 14 unmodified lines
12041219 dev->ieee80211_ptr->use_4addr = false;
12051220 rdev_set_qos_map(rdev, dev, NULL);
12061221
1207− cfg80211_leave(rdev, dev->ieee80211_ptr, -1);
1222+ cfg80211_leave_locked(rdev, dev->ieee80211_ptr, -1);
12081223
12091224 cfg80211_process_rdev_events(rdev);
12101225 cfg80211_mlme_purge_registrations(dev->ieee80211_ptr);
@@ -1232,6 +1247,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 21 unmodified lines
12321247 case NL80211_IFTYPE_OCB:
12331248 case NL80211_IFTYPE_P2P_CLIENT:
12341249 case NL80211_IFTYPE_ADHOC:
1250+ case NL80211_IFTYPE_NAN_DATA:
12351251 dev->priv_flags |= IFF_DONT_BRIDGE;
12361252 break;
12371253 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