History

Merge tag 'wireless-2025-06-18' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless

Johannes Berg says: ==================== More fixes: - ath12k - avoid busy-waiting - activate correct number of links - iwlwifi - iwldvm regression (lots of warnings) - iwlmld merge damage regression (crash) - fix build with some old gcc versions - carl9170: don't talk to device w/o FW [syzbot] - ath6kl: remove bad FW WARN [syzbot] - ieee80211: use variable-length arrays [syzbot] - mac80211 - remove WARN on delayed beacon update [syzbot] - drop OCB frames with invalid source [syzbot] * tag 'wireless-2025-06-18' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: wifi: iwlwifi: Fix incorrect logic on cmd_ver range checking wifi: iwlwifi: dvm: restore n_no_reclaim_cmds setting wifi: iwlwifi: cfg: Limit cb_size to valid range wifi: iwlwifi: restore missing initialization of async_handlers_list (again) wifi: ath6kl: remove WARN on bad firmware input wifi: carl9170: do not ping device which has failed to load firmware wifi: ath12k: don't wait when there is no vdev started wifi: ath12k: don't use static variables in ath12k_wmi_fw_stats_process() wifi: ath12k: avoid burning CPU while waiting for firmware stats wifi: ath12k: fix documentation on firmware stats wifi: ath12k: don't activate more links than firmware supports wifi: ath12k: update link active in case two links fall on the same MAC wifi: ath12k: support WMI_MLO_LINK_SET_ACTIVE_CMDID command wifi: ath12k: update freq range for each hardware mode wifi: ath12k: parse and save sbs_lower_band_end_freq from WMI_SERVICE_READY_EXT2_EVENTID event wifi: ath12k: parse and save hardware mode info from WMI_SERVICE_READY_EXT_EVENTID event for later use wifi: ath12k: Avoid CPU busy-wait by handling VDEV_STAT and BCN_STAT wifi: mac80211: don't WARN for late channel/color switch wifi: mac80211: drop invalid source address OCB frames wifi: remove zero-length arrays ====================

Jakub Kicinski committed 1 year ago

Commit dccf87e2 parents 9738280 68dd8ee18 files · +1445 −133Browse files

Unified · Split

18 files
  1. drivers/net/wireless/ath/ath12k/core.c +3 −1
  2. drivers/net/wireless/ath/ath12k/core.h +9 −1
  3. drivers/net/wireless/ath/ath12k/debugfs.c +0 −58
  4. drivers/net/wireless/ath/ath12k/debugfs.h +0 −7
  5. drivers/net/wireless/ath/ath12k/mac.c +370 −24
  6. drivers/net/wireless/ath/ath12k/mac.h +2 −0
  7. drivers/net/wireless/ath/ath12k/wmi.c +819 −10
  8. drivers/net/wireless/ath/ath12k/wmi.h +179 −1
  9. drivers/net/wireless/ath/ath6kl/bmi.c +3 −1
  10. drivers/net/wireless/ath/carl9170/usb.c +13 −6
  11. drivers/net/wireless/intel/iwlwifi/dvm/main.c +1 −0
  12. drivers/net/wireless/intel/iwlwifi/mld/mld.c +1 −0
  13. drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c +1 −1
  14. drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +6 −5
  15. include/linux/ieee80211.h +9 −9
  16. net/mac80211/debug.h +4 −1
  17. net/mac80211/rx.c +4 −0
  18. net/mac80211/tx.c +21 −8
drivers/net/wireless/ath/ath12k/core.c+3−1
@@ -1216,6 +1216,7 @@ void ath12k_fw_stats_init(struct ath12k *ar) · 1215 unmodified lines
12161216 INIT_LIST_HEAD(&ar->fw_stats.pdevs);
12171217 INIT_LIST_HEAD(&ar->fw_stats.bcn);
12181218 init_completion(&ar->fw_stats_complete);
1219+ init_completion(&ar->fw_stats_done);
12191220 }
12201221
12211222 void ath12k_fw_stats_free(struct ath12k_fw_stats *stats)
@@ -1228,8 +1229,9 @@ void ath12k_fw_stats_free(struct ath12k_fw_stats *stats) · 6 unmodified lines
12281229 void ath12k_fw_stats_reset(struct ath12k *ar)
12291230 {
12301231 spin_lock_bh(&ar->data_lock);
1231− ar->fw_stats.fw_stats_done = false;
12321232 ath12k_fw_stats_free(&ar->fw_stats);
1233+ ar->fw_stats.num_vdev_recvd = 0;
1234+ ar->fw_stats.num_bcn_recvd = 0;
12331235 spin_unlock_bh(&ar->data_lock);
12341236 }
12351237
drivers/net/wireless/ath/ath12k/core.h+9−1
@@ -601,6 +601,12 @@ struct ath12k_sta { · 600 unmodified lines
601601 #define ATH12K_NUM_CHANS 101
602602 #define ATH12K_MAX_5GHZ_CHAN 173
603603
604+static inline bool ath12k_is_2ghz_channel_freq(u32 freq)
605+{
606+ return freq >= ATH12K_MIN_2GHZ_FREQ &&
607+ freq <= ATH12K_MAX_2GHZ_FREQ;
608+}
609+
604610 enum ath12k_hw_state {
605611 ATH12K_HW_STATE_OFF,
606612 ATH12K_HW_STATE_ON,
@@ -626,7 +632,8 @@ struct ath12k_fw_stats { · 19 unmodified lines
626632 struct list_head pdevs;
627633 struct list_head vdevs;
628634 struct list_head bcn;
629− bool fw_stats_done;
635+ u32 num_vdev_recvd;
636+ u32 num_bcn_recvd;
630637 };
631638
632639 struct ath12k_dbg_htt_stats {
@@ -806,6 +813,7 @@ struct ath12k { · 173 unmodified lines
806813 bool regdom_set_by_user;
807814
808815 struct completion fw_stats_complete;
816+ struct completion fw_stats_done;
809817
810818 struct completion mlo_setup_done;
811819 u32 mlo_setup_status;
drivers/net/wireless/ath/ath12k/debugfs.c+0−58
@@ -1251,64 +1251,6 @@ void ath12k_debugfs_soc_destroy(struct ath12k_base *ab) · 1250 unmodified lines
12511251 */
12521252 }
12531253
1254−void
1255−ath12k_debugfs_fw_stats_process(struct ath12k *ar,
1256− struct ath12k_fw_stats *stats)
1257−{
1258− struct ath12k_base *ab = ar->ab;
1259− struct ath12k_pdev *pdev;
1260− bool is_end;
1261− static unsigned int num_vdev, num_bcn;
1262− size_t total_vdevs_started = 0;
1263− int i;
1264−
1265− if (stats->stats_id == WMI_REQUEST_VDEV_STAT) {
1266− if (list_empty(&stats->vdevs)) {
1267− ath12k_warn(ab, "empty vdev stats");
1268− return;
1269− }
1270− /* FW sends all the active VDEV stats irrespective of PDEV,
1271− * hence limit until the count of all VDEVs started
1272− */
1273− rcu_read_lock();
1274− for (i = 0; i < ab->num_radios; i++) {
1275− pdev = rcu_dereference(ab->pdevs_active[i]);
1276− if (pdev && pdev->ar)
1277− total_vdevs_started += pdev->ar->num_started_vdevs;
1278− }
1279− rcu_read_unlock();
1280−
1281− is_end = ((++num_vdev) == total_vdevs_started);
1282−
1283− list_splice_tail_init(&stats->vdevs,
1284− &ar->fw_stats.vdevs);
1285−
1286− if (is_end) {
1287− ar->fw_stats.fw_stats_done = true;
1288− num_vdev = 0;
1289− }
1290− return;
1291− }
1292− if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
1293− if (list_empty(&stats->bcn)) {
1294− ath12k_warn(ab, "empty beacon stats");
1295− return;
1296− }
1297− /* Mark end until we reached the count of all started VDEVs
1298− * within the PDEV
1299− */
1300− is_end = ((++num_bcn) == ar->num_started_vdevs);
1301−
1302− list_splice_tail_init(&stats->bcn,
1303− &ar->fw_stats.bcn);
1304−
1305− if (is_end) {
1306− ar->fw_stats.fw_stats_done = true;
1307− num_bcn = 0;
1308− }
1309− }
1310−}
1311−
13121254 static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)
13131255 {
13141256 struct ath12k *ar = inode->i_private;
drivers/net/wireless/ath/ath12k/debugfs.h+0−7
@@ -12,8 +12,6 @@ void ath12k_debugfs_soc_create(struct ath12k_base *ab); · 11 unmodified lines
1212 void ath12k_debugfs_soc_destroy(struct ath12k_base *ab);
1313 void ath12k_debugfs_register(struct ath12k *ar);
1414 void ath12k_debugfs_unregister(struct ath12k *ar);
15−void ath12k_debugfs_fw_stats_process(struct ath12k *ar,
16− struct ath12k_fw_stats *stats);
1715 void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
1816 struct ieee80211_vif *vif);
1917 void ath12k_debugfs_pdev_create(struct ath12k_base *ab);
@@ -126,11 +124,6 @@ static inline void ath12k_debugfs_unregister(struct ath12k *ar) · 106 unmodified lines
126124 {
127125 }
128126
129−static inline void ath12k_debugfs_fw_stats_process(struct ath12k *ar,
130− struct ath12k_fw_stats *stats)
131−{
132−}
133−
134127 static inline bool ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar)
135128 {
136129 return false;
drivers/net/wireless/ath/ath12k/mac.c+370−24
@@ -4360,7 +4360,7 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar, · 4359 unmodified lines
43604360 {
43614361 struct ath12k_base *ab = ar->ab;
43624362 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
4363− unsigned long timeout, time_left;
4363+ unsigned long time_left;
43644364 int ret;
43654365
43664366 guard(mutex)(&ah->hw_mutex);
@@ -4368,19 +4368,13 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar, · 1 unmodified line
43684368 if (ah->state != ATH12K_HW_STATE_ON)
43694369 return -ENETDOWN;
43704370
4371− /* FW stats can get split when exceeding the stats data buffer limit.
4372− * In that case, since there is no end marking for the back-to-back
4373− * received 'update stats' event, we keep a 3 seconds timeout in case,
4374− * fw_stats_done is not marked yet
4375− */
4376− timeout = jiffies + msecs_to_jiffies(3 * 1000);
43774371 ath12k_fw_stats_reset(ar);
43784372
43794373 reinit_completion(&ar->fw_stats_complete);
4374+ reinit_completion(&ar->fw_stats_done);
43804375
43814376 ret = ath12k_wmi_send_stats_request_cmd(ar, param->stats_id,
43824377 param->vdev_id, param->pdev_id);
4383−
43844378 if (ret) {
43854379 ath12k_warn(ab, "failed to request fw stats: %d\n", ret);
43864380 return ret;
@@ -4391,7 +4385,6 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar, · 4 unmodified lines
43914385 param->pdev_id, param->vdev_id, param->stats_id);
43924386
43934387 time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
4394−
43954388 if (!time_left) {
43964389 ath12k_warn(ab, "time out while waiting for get fw stats\n");
43974390 return -ETIMEDOUT;
@@ -4400,20 +4393,15 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar, · 2 unmodified lines
44004393 /* Firmware sends WMI_UPDATE_STATS_EVENTID back-to-back
44014394 * when stats data buffer limit is reached. fw_stats_complete
44024395 * is completed once host receives first event from firmware, but
4403− * still end might not be marked in the TLV.
4404− * Below loop is to confirm that firmware completed sending all the event
4405− * and fw_stats_done is marked true when end is marked in the TLV.
4396+ * still there could be more events following. Below is to wait
4397+ * until firmware completes sending all the events.
44064398 */
4407− for (;;) {
4408− if (time_after(jiffies, timeout))
4409− break;
4410− spin_lock_bh(&ar->data_lock);
4411− if (ar->fw_stats.fw_stats_done) {
4412− spin_unlock_bh(&ar->data_lock);
4413− break;
4414− }
4415− spin_unlock_bh(&ar->data_lock);
4399+ time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
4400+ if (!time_left) {
4401+ ath12k_warn(ab, "time out while waiting for fw stats done\n");
4402+ return -ETIMEDOUT;
44164403 }
4404+
44174405 return 0;
44184406 }
44194407
@@ -5890,6 +5878,327 @@ exit: · 1470 unmodified lines
58905878 return ret;
58915879 }
58925880
5881+static bool ath12k_mac_is_freq_on_mac(struct ath12k_hw_mode_freq_range_arg *freq_range,
5882+ u32 freq, u8 mac_id)
5883+{
5884+ return (freq >= freq_range[mac_id].low_2ghz_freq &&
5885+ freq <= freq_range[mac_id].high_2ghz_freq) ||
5886+ (freq >= freq_range[mac_id].low_5ghz_freq &&
5887+ freq <= freq_range[mac_id].high_5ghz_freq);
5888+}
5889+
5890+static bool
5891+ath12k_mac_2_freq_same_mac_in_freq_range(struct ath12k_base *ab,
5892+ struct ath12k_hw_mode_freq_range_arg *freq_range,
5893+ u32 freq_link1, u32 freq_link2)
5894+{
5895+ u8 i;
5896+
5897+ for (i = 0; i < MAX_RADIOS; i++) {
5898+ if (ath12k_mac_is_freq_on_mac(freq_range, freq_link1, i) &&
5899+ ath12k_mac_is_freq_on_mac(freq_range, freq_link2, i))
5900+ return true;
5901+ }
5902+
5903+ return false;
5904+}
5905+
5906+static bool ath12k_mac_is_hw_dbs_capable(struct ath12k_base *ab)
5907+{
5908+ return test_bit(WMI_TLV_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT,
5909+ ab->wmi_ab.svc_map) &&
5910+ ab->wmi_ab.hw_mode_info.support_dbs;
5911+}
5912+
5913+static bool ath12k_mac_2_freq_same_mac_in_dbs(struct ath12k_base *ab,
5914+ u32 freq_link1, u32 freq_link2)
5915+{
5916+ struct ath12k_hw_mode_freq_range_arg *freq_range;
5917+
5918+ if (!ath12k_mac_is_hw_dbs_capable(ab))
5919+ return true;
5920+
5921+ freq_range = ab->wmi_ab.hw_mode_info.freq_range_caps[ATH12K_HW_MODE_DBS];
5922+ return ath12k_mac_2_freq_same_mac_in_freq_range(ab, freq_range,
5923+ freq_link1, freq_link2);
5924+}
5925+
5926+static bool ath12k_mac_is_hw_sbs_capable(struct ath12k_base *ab)
5927+{
5928+ return test_bit(WMI_TLV_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT,
5929+ ab->wmi_ab.svc_map) &&
5930+ ab->wmi_ab.hw_mode_info.support_sbs;
5931+}
5932+
5933+static bool ath12k_mac_2_freq_same_mac_in_sbs(struct ath12k_base *ab,
5934+ u32 freq_link1, u32 freq_link2)
5935+{
5936+ struct ath12k_hw_mode_info *info = &ab->wmi_ab.hw_mode_info;
5937+ struct ath12k_hw_mode_freq_range_arg *sbs_uppr_share;
5938+ struct ath12k_hw_mode_freq_range_arg *sbs_low_share;
5939+ struct ath12k_hw_mode_freq_range_arg *sbs_range;
5940+
5941+ if (!ath12k_mac_is_hw_sbs_capable(ab))
5942+ return true;
5943+
5944+ if (ab->wmi_ab.sbs_lower_band_end_freq) {
5945+ sbs_uppr_share = info->freq_range_caps[ATH12K_HW_MODE_SBS_UPPER_SHARE];
5946+ sbs_low_share = info->freq_range_caps[ATH12K_HW_MODE_SBS_LOWER_SHARE];
5947+
5948+ return ath12k_mac_2_freq_same_mac_in_freq_range(ab, sbs_low_share,
5949+ freq_link1, freq_link2) ||
5950+ ath12k_mac_2_freq_same_mac_in_freq_range(ab, sbs_uppr_share,
5951+ freq_link1, freq_link2);
5952+ }
5953+
5954+ sbs_range = info->freq_range_caps[ATH12K_HW_MODE_SBS];
5955+ return ath12k_mac_2_freq_same_mac_in_freq_range(ab, sbs_range,
5956+ freq_link1, freq_link2);
5957+}
5958+
5959+static bool ath12k_mac_freqs_on_same_mac(struct ath12k_base *ab,
5960+ u32 freq_link1, u32 freq_link2)
5961+{
5962+ return ath12k_mac_2_freq_same_mac_in_dbs(ab, freq_link1, freq_link2) &&
5963+ ath12k_mac_2_freq_same_mac_in_sbs(ab, freq_link1, freq_link2);
5964+}
5965+
5966+static int ath12k_mac_mlo_sta_set_link_active(struct ath12k_base *ab,
5967+ enum wmi_mlo_link_force_reason reason,
5968+ enum wmi_mlo_link_force_mode mode,
5969+ u8 *mlo_vdev_id_lst,
5970+ u8 num_mlo_vdev,
5971+ u8 *mlo_inactive_vdev_lst,
5972+ u8 num_mlo_inactive_vdev)
5973+{
5974+ struct wmi_mlo_link_set_active_arg param = {0};
5975+ u32 entry_idx, entry_offset, vdev_idx;
5976+ u8 vdev_id;
5977+
5978+ param.reason = reason;
5979+ param.force_mode = mode;
5980+
5981+ for (vdev_idx = 0; vdev_idx < num_mlo_vdev; vdev_idx++) {
5982+ vdev_id = mlo_vdev_id_lst[vdev_idx];
5983+ entry_idx = vdev_id / 32;
5984+ entry_offset = vdev_id % 32;
5985+ if (entry_idx >= WMI_MLO_LINK_NUM_SZ) {
5986+ ath12k_warn(ab, "Invalid entry_idx %d num_mlo_vdev %d vdev %d",
5987+ entry_idx, num_mlo_vdev, vdev_id);
5988+ return -EINVAL;
5989+ }
5990+ param.vdev_bitmap[entry_idx] |= 1 << entry_offset;
5991+ /* update entry number if entry index changed */
5992+ if (param.num_vdev_bitmap < entry_idx + 1)
5993+ param.num_vdev_bitmap = entry_idx + 1;
5994+ }
5995+
5996+ ath12k_dbg(ab, ATH12K_DBG_MAC,
5997+ "num_vdev_bitmap %d vdev_bitmap[0] = 0x%x, vdev_bitmap[1] = 0x%x",
5998+ param.num_vdev_bitmap, param.vdev_bitmap[0], param.vdev_bitmap[1]);
5999+
6000+ if (mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE) {
6001+ for (vdev_idx = 0; vdev_idx < num_mlo_inactive_vdev; vdev_idx++) {
6002+ vdev_id = mlo_inactive_vdev_lst[vdev_idx];
6003+ entry_idx = vdev_id / 32;
6004+ entry_offset = vdev_id % 32;
6005+ if (entry_idx >= WMI_MLO_LINK_NUM_SZ) {
6006+ ath12k_warn(ab, "Invalid entry_idx %d num_mlo_vdev %d vdev %d",
6007+ entry_idx, num_mlo_inactive_vdev, vdev_id);
6008+ return -EINVAL;
6009+ }
6010+ param.inactive_vdev_bitmap[entry_idx] |= 1 << entry_offset;
6011+ /* update entry number if entry index changed */
6012+ if (param.num_inactive_vdev_bitmap < entry_idx + 1)
6013+ param.num_inactive_vdev_bitmap = entry_idx + 1;
6014+ }
6015+
6016+ ath12k_dbg(ab, ATH12K_DBG_MAC,
6017+ "num_vdev_bitmap %d inactive_vdev_bitmap[0] = 0x%x, inactive_vdev_bitmap[1] = 0x%x",
6018+ param.num_inactive_vdev_bitmap,
6019+ param.inactive_vdev_bitmap[0],
6020+ param.inactive_vdev_bitmap[1]);
6021+ }
6022+
6023+ if (mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_LINK_NUM ||
6024+ mode == WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM) {
6025+ param.num_link_entry = 1;
6026+ param.link_num[0].num_of_link = num_mlo_vdev - 1;
6027+ }
6028+
6029+ return ath12k_wmi_send_mlo_link_set_active_cmd(ab, &param);
6030+}
6031+
6032+static int ath12k_mac_mlo_sta_update_link_active(struct ath12k_base *ab,
6033+ struct ieee80211_hw *hw,
6034+ struct ath12k_vif *ahvif)
6035+{
6036+ u8 mlo_vdev_id_lst[IEEE80211_MLD_MAX_NUM_LINKS] = {0};
6037+ u32 mlo_freq_list[IEEE80211_MLD_MAX_NUM_LINKS] = {0};
6038+ unsigned long links = ahvif->links_map;
6039+ enum wmi_mlo_link_force_reason reason;
6040+ struct ieee80211_chanctx_conf *conf;
6041+ enum wmi_mlo_link_force_mode mode;
6042+ struct ieee80211_bss_conf *info;
6043+ struct ath12k_link_vif *arvif;
6044+ u8 num_mlo_vdev = 0;
6045+ u8 link_id;
6046+
6047+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
6048+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
6049+ /* make sure vdev is created on this device */
6050+ if (!arvif || !arvif->is_created || arvif->ar->ab != ab)
6051+ continue;
6052+
6053+ info = ath12k_mac_get_link_bss_conf(arvif);
6054+ conf = wiphy_dereference(hw->wiphy, info->chanctx_conf);
6055+ mlo_freq_list[num_mlo_vdev] = conf->def.chan->center_freq;
6056+
6057+ mlo_vdev_id_lst[num_mlo_vdev] = arvif->vdev_id;
6058+ num_mlo_vdev++;
6059+ }
6060+
6061+ /* It is not allowed to activate more links than a single device
6062+ * supported. Something goes wrong if we reach here.
6063+ */
6064+ if (num_mlo_vdev > ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE) {
6065+ WARN_ON_ONCE(1);
6066+ return -EINVAL;
6067+ }
6068+
6069+ /* if 2 links are established and both link channels fall on the
6070+ * same hardware MAC, send command to firmware to deactivate one
6071+ * of them.
6072+ */
6073+ if (num_mlo_vdev == 2 &&
6074+ ath12k_mac_freqs_on_same_mac(ab, mlo_freq_list[0],
6075+ mlo_freq_list[1])) {
6076+ mode = WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM;
6077+ reason = WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT;
6078+ return ath12k_mac_mlo_sta_set_link_active(ab, reason, mode,
6079+ mlo_vdev_id_lst, num_mlo_vdev,
6080+ NULL, 0);
6081+ }
6082+
6083+ return 0;
6084+}
6085+
6086+static bool ath12k_mac_are_sbs_chan(struct ath12k_base *ab, u32 freq_1, u32 freq_2)
6087+{
6088+ if (!ath12k_mac_is_hw_sbs_capable(ab))
6089+ return false;
6090+
6091+ if (ath12k_is_2ghz_channel_freq(freq_1) ||
6092+ ath12k_is_2ghz_channel_freq(freq_2))
6093+ return false;
6094+
6095+ return !ath12k_mac_2_freq_same_mac_in_sbs(ab, freq_1, freq_2);
6096+}
6097+
6098+static bool ath12k_mac_are_dbs_chan(struct ath12k_base *ab, u32 freq_1, u32 freq_2)
6099+{
6100+ if (!ath12k_mac_is_hw_dbs_capable(ab))
6101+ return false;
6102+
6103+ return !ath12k_mac_2_freq_same_mac_in_dbs(ab, freq_1, freq_2);
6104+}
6105+
6106+static int ath12k_mac_select_links(struct ath12k_base *ab,
6107+ struct ieee80211_vif *vif,
6108+ struct ieee80211_hw *hw,
6109+ u16 *selected_links)
6110+{
6111+ unsigned long useful_links = ieee80211_vif_usable_links(vif);
6112+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
6113+ u8 num_useful_links = hweight_long(useful_links);
6114+ struct ieee80211_chanctx_conf *chanctx;
6115+ struct ath12k_link_vif *assoc_arvif;
6116+ u32 assoc_link_freq, partner_freq;
6117+ u16 sbs_links = 0, dbs_links = 0;
6118+ struct ieee80211_bss_conf *info;
6119+ struct ieee80211_channel *chan;
6120+ struct ieee80211_sta *sta;
6121+ struct ath12k_sta *ahsta;
6122+ u8 link_id;
6123+
6124+ /* activate all useful links if less than max supported */
6125+ if (num_useful_links <= ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE) {
6126+ *selected_links = useful_links;
6127+ return 0;
6128+ }
6129+
6130+ /* only in station mode we can get here, so it's safe
6131+ * to use ap_addr
6132+ */
6133+ rcu_read_lock();
6134+ sta = ieee80211_find_sta(vif, vif->cfg.ap_addr);
6135+ if (!sta) {
6136+ rcu_read_unlock();
6137+ ath12k_warn(ab, "failed to find sta with addr %pM\n", vif->cfg.ap_addr);
6138+ return -EINVAL;
6139+ }
6140+
6141+ ahsta = ath12k_sta_to_ahsta(sta);
6142+ assoc_arvif = wiphy_dereference(hw->wiphy, ahvif->link[ahsta->assoc_link_id]);
6143+ info = ath12k_mac_get_link_bss_conf(assoc_arvif);
6144+ chanctx = rcu_dereference(info->chanctx_conf);
6145+ assoc_link_freq = chanctx->def.chan->center_freq;
6146+ rcu_read_unlock();
6147+ ath12k_dbg(ab, ATH12K_DBG_MAC, "assoc link %u freq %u\n",
6148+ assoc_arvif->link_id, assoc_link_freq);
6149+
6150+ /* assoc link is already activated and has to be kept active,
6151+ * only need to select a partner link from others.
6152+ */
6153+ useful_links &= ~BIT(assoc_arvif->link_id);
6154+ for_each_set_bit(link_id, &useful_links, IEEE80211_MLD_MAX_NUM_LINKS) {
6155+ info = wiphy_dereference(hw->wiphy, vif->link_conf[link_id]);
6156+ if (!info) {
6157+ ath12k_warn(ab, "failed to get link info for link: %u\n",
6158+ link_id);
6159+ return -ENOLINK;
6160+ }
6161+
6162+ chan = info->chanreq.oper.chan;
6163+ if (!chan) {
6164+ ath12k_warn(ab, "failed to get chan for link: %u\n", link_id);
6165+ return -EINVAL;
6166+ }
6167+
6168+ partner_freq = chan->center_freq;
6169+ if (ath12k_mac_are_sbs_chan(ab, assoc_link_freq, partner_freq)) {
6170+ sbs_links |= BIT(link_id);
6171+ ath12k_dbg(ab, ATH12K_DBG_MAC, "new SBS link %u freq %u\n",
6172+ link_id, partner_freq);
6173+ continue;
6174+ }
6175+
6176+ if (ath12k_mac_are_dbs_chan(ab, assoc_link_freq, partner_freq)) {
6177+ dbs_links |= BIT(link_id);
6178+ ath12k_dbg(ab, ATH12K_DBG_MAC, "new DBS link %u freq %u\n",
6179+ link_id, partner_freq);
6180+ continue;
6181+ }
6182+
6183+ ath12k_dbg(ab, ATH12K_DBG_MAC, "non DBS/SBS link %u freq %u\n",
6184+ link_id, partner_freq);
6185+ }
6186+
6187+ /* choose the first candidate no matter how many is in the list */
6188+ if (sbs_links)
6189+ link_id = __ffs(sbs_links);
6190+ else if (dbs_links)
6191+ link_id = __ffs(dbs_links);
6192+ else
6193+ link_id = ffs(useful_links) - 1;
6194+
6195+ ath12k_dbg(ab, ATH12K_DBG_MAC, "select partner link %u\n", link_id);
6196+
6197+ *selected_links = BIT(assoc_arvif->link_id) | BIT(link_id);
6198+
6199+ return 0;
6200+}
6201+
58936202 static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
58946203 struct ieee80211_vif *vif,
58956204 struct ieee80211_sta *sta,
@@ -5899,10 +6208,13 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, · 3 unmodified lines
58996208 struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
59006209 struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
59016210 struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
6211+ struct ath12k_base *prev_ab = NULL, *ab;
59026212 struct ath12k_link_vif *arvif;
59036213 struct ath12k_link_sta *arsta;
59046214 unsigned long valid_links;
5905− u8 link_id = 0;
6215+ u16 selected_links = 0;
6216+ u8 link_id = 0, i;
6217+ struct ath12k *ar;
59066218 int ret;
59076219
59086220 lockdep_assert_wiphy(hw->wiphy);
@@ -5972,8 +6284,24 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, · 63 unmodified lines
59726284 * about to move to the associated state.
59736285 */
59746286 if (ieee80211_vif_is_mld(vif) && vif->type == NL80211_IFTYPE_STATION &&
5975− old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC)
5976− ieee80211_set_active_links(vif, ieee80211_vif_usable_links(vif));
6287+ old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) {
6288+ /* TODO: for now only do link selection for single device
6289+ * MLO case. Other cases would be handled in the future.
6290+ */
6291+ ab = ah->radio[0].ab;
6292+ if (ab->ag->num_devices == 1) {
6293+ ret = ath12k_mac_select_links(ab, vif, hw, &selected_links);
6294+ if (ret) {
6295+ ath12k_warn(ab,
6296+ "failed to get selected links: %d\n", ret);
6297+ goto exit;
6298+ }
6299+ } else {
6300+ selected_links = ieee80211_vif_usable_links(vif);
6301+ }
6302+
6303+ ieee80211_set_active_links(vif, selected_links);
6304+ }
59776305
59786306 /* Handle all the other state transitions in generic way */
59796307 valid_links = ahsta->links_map;
@@ -5997,6 +6325,24 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, · 17 unmodified lines
59976325 }
59986326 }
59996327
6328+ if (ieee80211_vif_is_mld(vif) && vif->type == NL80211_IFTYPE_STATION &&
6329+ old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) {
6330+ for_each_ar(ah, ar, i) {
6331+ ab = ar->ab;
6332+ if (prev_ab == ab)
6333+ continue;
6334+
6335+ ret = ath12k_mac_mlo_sta_update_link_active(ab, hw, ahvif);
6336+ if (ret) {
6337+ ath12k_warn(ab,
6338+ "failed to update link active state on connect %d\n",
6339+ ret);
6340+ goto exit;
6341+ }
6342+
6343+ prev_ab = ab;
6344+ }
6345+ }
60006346 /* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST:
60016347 * Remove the station from driver (handle ML sta here since that
60026348 * needs special handling. Normal sta will be handled in generic
drivers/net/wireless/ath/ath12k/mac.h+2−0
@@ -54,6 +54,8 @@ struct ath12k_generic_iter { · 53 unmodified lines
5454 #define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS
5555 #define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1)
5656
57+#define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2
58+
5759 enum ath12k_supported_bw {
5860 ATH12K_BW_20 = 0,
5961 ATH12K_BW_40 = 1,
drivers/net/wireless/ath/ath12k/wmi.c+819−10
@@ -91,6 +91,11 @@ struct ath12k_wmi_svc_rdy_ext2_parse { · 90 unmodified lines
9191 bool dma_ring_cap_done;
9292 bool spectral_bin_scaling_done;
9393 bool mac_phy_caps_ext_done;
94+ bool hal_reg_caps_ext2_done;
95+ bool scan_radio_caps_ext2_done;
96+ bool twt_caps_done;
97+ bool htt_msdu_idx_to_qtype_map_done;
98+ bool dbs_or_sbs_cap_ext_done;
9499 };
95100
96101 struct ath12k_wmi_rdy_parse {
@@ -4395,6 +4400,7 @@ static int ath12k_wmi_hw_mode_caps_parse(struct ath12k_base *soc, · 4298 unmodified lines
43954400 static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
43964401 u16 len, const void *ptr, void *data)
43974402 {
4403+ struct ath12k_svc_ext_info *svc_ext_info = &soc->wmi_ab.svc_ext_info;
43984404 struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;
43994405 const struct ath12k_wmi_hw_mode_cap_params *hw_mode_caps;
44004406 enum wmi_host_hw_mode_config_type mode, pref;
@@ -4427,8 +4433,11 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc, · 26 unmodified lines
44274433 }
44284434 }
44294435
4430− ath12k_dbg(soc, ATH12K_DBG_WMI, "preferred_hw_mode:%d\n",
4431− soc->wmi_ab.preferred_hw_mode);
4436+ svc_ext_info->num_hw_modes = svc_rdy_ext->n_hw_mode_caps;
4437+
4438+ ath12k_dbg(soc, ATH12K_DBG_WMI, "num hw modes %u preferred_hw_mode %d\n",
4439+ svc_ext_info->num_hw_modes, soc->wmi_ab.preferred_hw_mode);
4440+
44324441 if (soc->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
44334442 return -EINVAL;
44344443
@@ -4658,6 +4667,65 @@ free_dir_buff: · 223 unmodified lines
46584667 return ret;
46594668 }
46604669
4670+static void
4671+ath12k_wmi_save_mac_phy_info(struct ath12k_base *ab,
4672+ const struct ath12k_wmi_mac_phy_caps_params *mac_phy_cap,
4673+ struct ath12k_svc_ext_mac_phy_info *mac_phy_info)
4674+{
4675+ mac_phy_info->phy_id = __le32_to_cpu(mac_phy_cap->phy_id);
4676+ mac_phy_info->supported_bands = __le32_to_cpu(mac_phy_cap->supported_bands);
4677+ mac_phy_info->hw_freq_range.low_2ghz_freq =
4678+ __le32_to_cpu(mac_phy_cap->low_2ghz_chan_freq);
4679+ mac_phy_info->hw_freq_range.high_2ghz_freq =
4680+ __le32_to_cpu(mac_phy_cap->high_2ghz_chan_freq);
4681+ mac_phy_info->hw_freq_range.low_5ghz_freq =
4682+ __le32_to_cpu(mac_phy_cap->low_5ghz_chan_freq);
4683+ mac_phy_info->hw_freq_range.high_5ghz_freq =
4684+ __le32_to_cpu(mac_phy_cap->high_5ghz_chan_freq);
4685+}
4686+
4687+static void
4688+ath12k_wmi_save_all_mac_phy_info(struct ath12k_base *ab,
4689+ struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext)
4690+{
4691+ struct ath12k_svc_ext_info *svc_ext_info = &ab->wmi_ab.svc_ext_info;
4692+ const struct ath12k_wmi_mac_phy_caps_params *mac_phy_cap;
4693+ const struct ath12k_wmi_hw_mode_cap_params *hw_mode_cap;
4694+ struct ath12k_svc_ext_mac_phy_info *mac_phy_info;
4695+ u32 hw_mode_id, phy_bit_map;
4696+ u8 hw_idx;
4697+
4698+ mac_phy_info = &svc_ext_info->mac_phy_info[0];
4699+ mac_phy_cap = svc_rdy_ext->mac_phy_caps;
4700+
4701+ for (hw_idx = 0; hw_idx < svc_ext_info->num_hw_modes; hw_idx++) {
4702+ hw_mode_cap = &svc_rdy_ext->hw_mode_caps[hw_idx];
4703+ hw_mode_id = __le32_to_cpu(hw_mode_cap->hw_mode_id);
4704+ phy_bit_map = __le32_to_cpu(hw_mode_cap->phy_id_map);
4705+
4706+ while (phy_bit_map) {
4707+ ath12k_wmi_save_mac_phy_info(ab, mac_phy_cap, mac_phy_info);
4708+ mac_phy_info->hw_mode_config_type =
4709+ le32_get_bits(hw_mode_cap->hw_mode_config_type,
4710+ WMI_HW_MODE_CAP_CFG_TYPE);
4711+ ath12k_dbg(ab, ATH12K_DBG_WMI,
4712+ "hw_idx %u hw_mode_id %u hw_mode_config_type %u supported_bands %u phy_id %u 2 GHz [%u - %u] 5 GHz [%u - %u]\n",
4713+ hw_idx, hw_mode_id,
4714+ mac_phy_info->hw_mode_config_type,
4715+ mac_phy_info->supported_bands, mac_phy_info->phy_id,
4716+ mac_phy_info->hw_freq_range.low_2ghz_freq,
4717+ mac_phy_info->hw_freq_range.high_2ghz_freq,
4718+ mac_phy_info->hw_freq_range.low_5ghz_freq,
4719+ mac_phy_info->hw_freq_range.high_5ghz_freq);
4720+
4721+ mac_phy_cap++;
4722+ mac_phy_info++;
4723+
4724+ phy_bit_map >>= 1;
4725+ }
4726+ }
4727+}
4728+
46614729 static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab,
46624730 u16 tag, u16 len,
46634731 const void *ptr, void *data)
@@ -4706,6 +4774,8 @@ static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab, · 42 unmodified lines
47064774 return ret;
47074775 }
47084776
4777+ ath12k_wmi_save_all_mac_phy_info(ab, svc_rdy_ext);
4778+
47094779 svc_rdy_ext->mac_phy_done = true;
47104780 } else if (!svc_rdy_ext->ext_hal_reg_done) {
47114781 ret = ath12k_wmi_ext_hal_reg_caps(ab, len, ptr, svc_rdy_ext);
@@ -4922,10 +4992,449 @@ static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag, · 210 unmodified lines
49224992 return 0;
49234993 }
49244994
4995+static void
4996+ath12k_wmi_update_freq_info(struct ath12k_base *ab,
4997+ struct ath12k_svc_ext_mac_phy_info *mac_cap,
4998+ enum ath12k_hw_mode mode,
4999+ u32 phy_id)
5000+{
5001+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info;
5002+ struct ath12k_hw_mode_freq_range_arg *mac_range;
5003+
5004+ mac_range = &hw_mode_info->freq_range_caps[mode][phy_id];
5005+
5006+ if (mac_cap->supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
5007+ mac_range->low_2ghz_freq = max_t(u32,
5008+ mac_cap->hw_freq_range.low_2ghz_freq,
5009+ ATH12K_MIN_2GHZ_FREQ);
5010+ mac_range->high_2ghz_freq = mac_cap->hw_freq_range.high_2ghz_freq ?
5011+ min_t(u32,
5012+ mac_cap->hw_freq_range.high_2ghz_freq,
5013+ ATH12K_MAX_2GHZ_FREQ) :
5014+ ATH12K_MAX_2GHZ_FREQ;
5015+ }
5016+
5017+ if (mac_cap->supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
5018+ mac_range->low_5ghz_freq = max_t(u32,
5019+ mac_cap->hw_freq_range.low_5ghz_freq,
5020+ ATH12K_MIN_5GHZ_FREQ);
5021+ mac_range->high_5ghz_freq = mac_cap->hw_freq_range.high_5ghz_freq ?
5022+ min_t(u32,
5023+ mac_cap->hw_freq_range.high_5ghz_freq,
5024+ ATH12K_MAX_6GHZ_FREQ) :
5025+ ATH12K_MAX_6GHZ_FREQ;
5026+ }
5027+}
5028+
5029+static bool
5030+ath12k_wmi_all_phy_range_updated(struct ath12k_base *ab,
5031+ enum ath12k_hw_mode hwmode)
5032+{
5033+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info;
5034+ struct ath12k_hw_mode_freq_range_arg *mac_range;
5035+ u8 phy_id;
5036+
5037+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) {
5038+ mac_range = &hw_mode_info->freq_range_caps[hwmode][phy_id];
5039+ /* modify SBS/DBS range only when both phy for DBS are filled */
5040+ if (!mac_range->low_2ghz_freq && !mac_range->low_5ghz_freq)
5041+ return false;
5042+ }
5043+
5044+ return true;
5045+}
5046+
5047+static void ath12k_wmi_update_dbs_freq_info(struct ath12k_base *ab)
5048+{
5049+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info;
5050+ struct ath12k_hw_mode_freq_range_arg *mac_range;
5051+ u8 phy_id;
5052+
5053+ mac_range = hw_mode_info->freq_range_caps[ATH12K_HW_MODE_DBS];
5054+ /* Reset 5 GHz range for shared mac for DBS */
5055+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) {
5056+ if (mac_range[phy_id].low_2ghz_freq &&
5057+ mac_range[phy_id].low_5ghz_freq) {
5058+ mac_range[phy_id].low_5ghz_freq = 0;
5059+ mac_range[phy_id].high_5ghz_freq = 0;
5060+ }
5061+ }
5062+}
5063+
5064+static u32
5065+ath12k_wmi_get_highest_5ghz_freq_from_range(struct ath12k_hw_mode_freq_range_arg *range)
5066+{
5067+ u32 highest_freq = 0;
5068+ u8 phy_id;
5069+
5070+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) {
5071+ if (range[phy_id].high_5ghz_freq > highest_freq)
5072+ highest_freq = range[phy_id].high_5ghz_freq;
5073+ }
5074+
5075+ return highest_freq ? highest_freq : ATH12K_MAX_6GHZ_FREQ;
5076+}
5077+
5078+static u32
5079+ath12k_wmi_get_lowest_5ghz_freq_from_range(struct ath12k_hw_mode_freq_range_arg *range)
5080+{
5081+ u32 lowest_freq = 0;
5082+ u8 phy_id;
5083+
5084+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) {
5085+ if ((!lowest_freq && range[phy_id].low_5ghz_freq) ||
5086+ range[phy_id].low_5ghz_freq < lowest_freq)
5087+ lowest_freq = range[phy_id].low_5ghz_freq;
5088+ }
5089+
5090+ return lowest_freq ? lowest_freq : ATH12K_MIN_5GHZ_FREQ;
5091+}
5092+
5093+static void
5094+ath12k_wmi_fill_upper_share_sbs_freq(struct ath12k_base *ab,
5095+ u16 sbs_range_sep,
5096+ struct ath12k_hw_mode_freq_range_arg *ref_freq)
5097+{
5098+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info;
5099+ struct ath12k_hw_mode_freq_range_arg *upper_sbs_freq_range;
5100+ u8 phy_id;
5101+
5102+ upper_sbs_freq_range =
5103+ hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS_UPPER_SHARE];
5104+
5105+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) {
5106+ upper_sbs_freq_range[phy_id].low_2ghz_freq =
5107+ ref_freq[phy_id].low_2ghz_freq;
5108+ upper_sbs_freq_range[phy_id].high_2ghz_freq =
5109+ ref_freq[phy_id].high_2ghz_freq;
5110+
5111+ /* update for shared mac */
5112+ if (upper_sbs_freq_range[phy_id].low_2ghz_freq) {
5113+ upper_sbs_freq_range[phy_id].low_5ghz_freq = sbs_range_sep + 10;
5114+ upper_sbs_freq_range[phy_id].high_5ghz_freq =
5115+ ath12k_wmi_get_highest_5ghz_freq_from_range(ref_freq);
5116+ } else {
5117+ upper_sbs_freq_range[phy_id].low_5ghz_freq =
5118+ ath12k_wmi_get_lowest_5ghz_freq_from_range(ref_freq);
5119+ upper_sbs_freq_range[phy_id].high_5ghz_freq = sbs_range_sep;
5120+ }
5121+ }
5122+}
5123+
5124+static void
5125+ath12k_wmi_fill_lower_share_sbs_freq(struct ath12k_base *ab,
5126+ u16 sbs_range_sep,
5127+ struct ath12k_hw_mode_freq_range_arg *ref_freq)
5128+{
5129+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info;
5130+ struct ath12k_hw_mode_freq_range_arg *lower_sbs_freq_range;
5131+ u8 phy_id;
5132+
5133+ lower_sbs_freq_range =
5134+ hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS_LOWER_SHARE];
5135+
5136+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) {
5137+ lower_sbs_freq_range[phy_id].low_2ghz_freq =
5138+ ref_freq[phy_id].low_2ghz_freq;
5139+ lower_sbs_freq_range[phy_id].high_2ghz_freq =
5140+ ref_freq[phy_id].high_2ghz_freq;
5141+
5142+ /* update for shared mac */
5143+ if (lower_sbs_freq_range[phy_id].low_2ghz_freq) {
5144+ lower_sbs_freq_range[phy_id].low_5ghz_freq =
5145+ ath12k_wmi_get_lowest_5ghz_freq_from_range(ref_freq);
5146+ lower_sbs_freq_range[phy_id].high_5ghz_freq = sbs_range_sep;
5147+ } else {
5148+ lower_sbs_freq_range[phy_id].low_5ghz_freq = sbs_range_sep + 10;
5149+ lower_sbs_freq_range[phy_id].high_5ghz_freq =
5150+ ath12k_wmi_get_highest_5ghz_freq_from_range(ref_freq);
5151+ }
5152+ }
5153+}
5154+
5155+static const char *ath12k_wmi_hw_mode_to_str(enum ath12k_hw_mode hw_mode)
5156+{
5157+ static const char * const mode_str[] = {
5158+ [ATH12K_HW_MODE_SMM] = "SMM",
5159+ [ATH12K_HW_MODE_DBS] = "DBS",
5160+ [ATH12K_HW_MODE_SBS] = "SBS",
5161+ [ATH12K_HW_MODE_SBS_UPPER_SHARE] = "SBS_UPPER_SHARE",
5162+ [ATH12K_HW_MODE_SBS_LOWER_SHARE] = "SBS_LOWER_SHARE",
5163+ };
5164+
5165+ if (hw_mode >= ARRAY_SIZE(mode_str))
5166+ return "Unknown";
5167+
5168+ return mode_str[hw_mode];
5169+}
5170+
5171+static void
5172+ath12k_wmi_dump_freq_range_per_mac(struct ath12k_base *ab,
5173+ struct ath12k_hw_mode_freq_range_arg *freq_range,
5174+ enum ath12k_hw_mode hw_mode)
5175+{
5176+ u8 i;
5177+
5178+ for (i = 0; i < MAX_RADIOS; i++)
5179+ if (freq_range[i].low_2ghz_freq || freq_range[i].low_5ghz_freq)
5180+ ath12k_dbg(ab, ATH12K_DBG_WMI,
5181+ "frequency range: %s(%d) mac %d 2 GHz [%d - %d] 5 GHz [%d - %d]",
5182+ ath12k_wmi_hw_mode_to_str(hw_mode),
5183+ hw_mode, i,
5184+ freq_range[i].low_2ghz_freq,
5185+ freq_range[i].high_2ghz_freq,
5186+ freq_range[i].low_5ghz_freq,
5187+ freq_range[i].high_5ghz_freq);
5188+}
5189+
5190+static void ath12k_wmi_dump_freq_range(struct ath12k_base *ab)
5191+{
5192+ struct ath12k_hw_mode_freq_range_arg *freq_range;
5193+ u8 i;
5194+
5195+ for (i = ATH12K_HW_MODE_SMM; i < ATH12K_HW_MODE_MAX; i++) {
5196+ freq_range = ab->wmi_ab.hw_mode_info.freq_range_caps[i];
5197+ ath12k_wmi_dump_freq_range_per_mac(ab, freq_range, i);
5198+ }
5199+}
5200+
5201+static int ath12k_wmi_modify_sbs_freq(struct ath12k_base *ab, u8 phy_id)
5202+{
5203+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info;
5204+ struct ath12k_hw_mode_freq_range_arg *sbs_mac_range, *shared_mac_range;
5205+ struct ath12k_hw_mode_freq_range_arg *non_shared_range;
5206+ u8 shared_phy_id;
5207+
5208+ sbs_mac_range = &hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS][phy_id];
5209+
5210+ /* if SBS mac range has both 2.4 and 5 GHz ranges, i.e. shared phy_id
5211+ * keep the range as it is in SBS
5212+ */
5213+ if (sbs_mac_range->low_2ghz_freq && sbs_mac_range->low_5ghz_freq)
5214+ return 0;
5215+
5216+ if (sbs_mac_range->low_2ghz_freq && !sbs_mac_range->low_5ghz_freq) {
5217+ ath12k_err(ab, "Invalid DBS/SBS mode with only 2.4Ghz");
5218+ ath12k_wmi_dump_freq_range_per_mac(ab, sbs_mac_range, ATH12K_HW_MODE_SBS);
5219+ return -EINVAL;
5220+ }
5221+
5222+ non_shared_range = sbs_mac_range;
5223+ /* if SBS mac range has only 5 GHz then it's the non-shared phy, so
5224+ * modify the range as per the shared mac.
5225+ */
5226+ shared_phy_id = phy_id ? 0 : 1;
5227+ shared_mac_range =
5228+ &hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS][shared_phy_id];
5229+
5230+ if (shared_mac_range->low_5ghz_freq > non_shared_range->low_5ghz_freq) {
5231+ ath12k_dbg(ab, ATH12K_DBG_WMI, "high 5 GHz shared");
5232+ /* If the shared mac lower 5 GHz frequency is greater than
5233+ * non-shared mac lower 5 GHz frequency then the shared mac has
5234+ * high 5 GHz shared with 2.4 GHz. So non-shared mac's 5 GHz high
5235+ * freq should be less than the shared mac's low 5 GHz freq.
5236+ */
5237+ if (non_shared_range->high_5ghz_freq >=
5238+ shared_mac_range->low_5ghz_freq)
5239+ non_shared_range->high_5ghz_freq =
5240+ max_t(u32, shared_mac_range->low_5ghz_freq - 10,
5241+ non_shared_range->low_5ghz_freq);
5242+ } else if (shared_mac_range->high_5ghz_freq <
5243+ non_shared_range->high_5ghz_freq) {
5244+ ath12k_dbg(ab, ATH12K_DBG_WMI, "low 5 GHz shared");
5245+ /* If the shared mac high 5 GHz frequency is less than
5246+ * non-shared mac high 5 GHz frequency then the shared mac has
5247+ * low 5 GHz shared with 2.4 GHz. So non-shared mac's 5 GHz low
5248+ * freq should be greater than the shared mac's high 5 GHz freq.
5249+ */
5250+ if (shared_mac_range->high_5ghz_freq >=
5251+ non_shared_range->low_5ghz_freq)
5252+ non_shared_range->low_5ghz_freq =
5253+ min_t(u32, shared_mac_range->high_5ghz_freq + 10,
5254+ non_shared_range->high_5ghz_freq);
5255+ } else {
5256+ ath12k_warn(ab, "invalid SBS range with all 5 GHz shared");
5257+ return -EINVAL;
5258+ }
5259+
5260+ return 0;
5261+}
5262+
5263+static void ath12k_wmi_update_sbs_freq_info(struct ath12k_base *ab)
5264+{
5265+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info;
5266+ struct ath12k_hw_mode_freq_range_arg *mac_range;
5267+ u16 sbs_range_sep;
5268+ u8 phy_id;
5269+ int ret;
5270+
5271+ mac_range = hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS];
5272+
5273+ /* If sbs_lower_band_end_freq has a value, then the frequency range
5274+ * will be split using that value.
5275+ */
5276+ sbs_range_sep = ab->wmi_ab.sbs_lower_band_end_freq;
5277+ if (sbs_range_sep) {
5278+ ath12k_wmi_fill_upper_share_sbs_freq(ab, sbs_range_sep,
5279+ mac_range);
5280+ ath12k_wmi_fill_lower_share_sbs_freq(ab, sbs_range_sep,
5281+ mac_range);
5282+ /* Hardware specifies the range boundary with sbs_range_sep,
5283+ * (i.e. the boundary between 5 GHz high and 5 GHz low),
5284+ * reset the original one to make sure it will not get used.
5285+ */
5286+ memset(mac_range, 0, sizeof(*mac_range) * MAX_RADIOS);
5287+ return;
5288+ }
5289+
5290+ /* If sbs_lower_band_end_freq is not set that means firmware will send one
5291+ * shared mac range and one non-shared mac range. so update that freq.
5292+ */
5293+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) {
5294+ ret = ath12k_wmi_modify_sbs_freq(ab, phy_id);
5295+ if (ret) {
5296+ memset(mac_range, 0, sizeof(*mac_range) * MAX_RADIOS);
5297+ break;
5298+ }
5299+ }
5300+}
5301+
5302+static void
5303+ath12k_wmi_update_mac_freq_info(struct ath12k_base *ab,
5304+ enum wmi_host_hw_mode_config_type hw_config_type,
5305+ u32 phy_id,
5306+ struct ath12k_svc_ext_mac_phy_info *mac_cap)
5307+{
5308+ if (phy_id >= MAX_RADIOS) {
5309+ ath12k_err(ab, "mac more than two not supported: %d", phy_id);
5310+ return;
5311+ }
5312+
5313+ ath12k_dbg(ab, ATH12K_DBG_WMI,
5314+ "hw_mode_cfg %d mac %d band 0x%x SBS cutoff freq %d 2 GHz [%d - %d] 5 GHz [%d - %d]",
5315+ hw_config_type, phy_id, mac_cap->supported_bands,
5316+ ab->wmi_ab.sbs_lower_band_end_freq,
5317+ mac_cap->hw_freq_range.low_2ghz_freq,
5318+ mac_cap->hw_freq_range.high_2ghz_freq,
5319+ mac_cap->hw_freq_range.low_5ghz_freq,
5320+ mac_cap->hw_freq_range.high_5ghz_freq);
5321+
5322+ switch (hw_config_type) {
5323+ case WMI_HOST_HW_MODE_SINGLE:
5324+ if (phy_id) {
5325+ ath12k_dbg(ab, ATH12K_DBG_WMI, "mac phy 1 is not supported");
5326+ break;
5327+ }
5328+ ath12k_wmi_update_freq_info(ab, mac_cap, ATH12K_HW_MODE_SMM, phy_id);
5329+ break;
5330+
5331+ case WMI_HOST_HW_MODE_DBS:
5332+ if (!ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_DBS))
5333+ ath12k_wmi_update_freq_info(ab, mac_cap,
5334+ ATH12K_HW_MODE_DBS, phy_id);
5335+ break;
5336+ case WMI_HOST_HW_MODE_DBS_SBS:
5337+ case WMI_HOST_HW_MODE_DBS_OR_SBS:
5338+ ath12k_wmi_update_freq_info(ab, mac_cap, ATH12K_HW_MODE_DBS, phy_id);
5339+ if (ab->wmi_ab.sbs_lower_band_end_freq ||
5340+ mac_cap->hw_freq_range.low_5ghz_freq ||
5341+ mac_cap->hw_freq_range.low_2ghz_freq)
5342+ ath12k_wmi_update_freq_info(ab, mac_cap, ATH12K_HW_MODE_SBS,
5343+ phy_id);
5344+
5345+ if (ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_DBS))
5346+ ath12k_wmi_update_dbs_freq_info(ab);
5347+ if (ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS))
5348+ ath12k_wmi_update_sbs_freq_info(ab);
5349+ break;
5350+ case WMI_HOST_HW_MODE_SBS:
5351+ case WMI_HOST_HW_MODE_SBS_PASSIVE:
5352+ ath12k_wmi_update_freq_info(ab, mac_cap, ATH12K_HW_MODE_SBS, phy_id);
5353+ if (ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS))
5354+ ath12k_wmi_update_sbs_freq_info(ab);
5355+
5356+ break;
5357+ default:
5358+ break;
5359+ }
5360+}
5361+
5362+static bool ath12k_wmi_sbs_range_present(struct ath12k_base *ab)
5363+{
5364+ if (ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS) ||
5365+ (ab->wmi_ab.sbs_lower_band_end_freq &&
5366+ ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS_LOWER_SHARE) &&
5367+ ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS_UPPER_SHARE)))
5368+ return true;
5369+
5370+ return false;
5371+}
5372+
5373+static int ath12k_wmi_update_hw_mode_list(struct ath12k_base *ab)
5374+{
5375+ struct ath12k_svc_ext_info *svc_ext_info = &ab->wmi_ab.svc_ext_info;
5376+ struct ath12k_hw_mode_info *info = &ab->wmi_ab.hw_mode_info;
5377+ enum wmi_host_hw_mode_config_type hw_config_type;
5378+ struct ath12k_svc_ext_mac_phy_info *tmp;
5379+ bool dbs_mode = false, sbs_mode = false;
5380+ u32 i, j = 0;
5381+
5382+ if (!svc_ext_info->num_hw_modes) {
5383+ ath12k_err(ab, "invalid number of hw modes");
5384+ return -EINVAL;
5385+ }
5386+
5387+ ath12k_dbg(ab, ATH12K_DBG_WMI, "updated HW mode list: num modes %d",
5388+ svc_ext_info->num_hw_modes);
5389+
5390+ memset(info->freq_range_caps, 0, sizeof(info->freq_range_caps));
5391+
5392+ for (i = 0; i < svc_ext_info->num_hw_modes; i++) {
5393+ if (j >= ATH12K_MAX_MAC_PHY_CAP)
5394+ return -EINVAL;
5395+
5396+ /* Update for MAC0 */
5397+ tmp = &svc_ext_info->mac_phy_info[j++];
5398+ hw_config_type = tmp->hw_mode_config_type;
5399+ ath12k_wmi_update_mac_freq_info(ab, hw_config_type, tmp->phy_id, tmp);
5400+
5401+ /* SBS and DBS have dual MAC. Up to 2 MACs are considered. */
5402+ if (hw_config_type == WMI_HOST_HW_MODE_DBS ||
5403+ hw_config_type == WMI_HOST_HW_MODE_SBS_PASSIVE ||
5404+ hw_config_type == WMI_HOST_HW_MODE_SBS ||
5405+ hw_config_type == WMI_HOST_HW_MODE_DBS_OR_SBS) {
5406+ if (j >= ATH12K_MAX_MAC_PHY_CAP)
5407+ return -EINVAL;
5408+ /* Update for MAC1 */
5409+ tmp = &svc_ext_info->mac_phy_info[j++];
5410+ ath12k_wmi_update_mac_freq_info(ab, hw_config_type,
5411+ tmp->phy_id, tmp);
5412+
5413+ if (hw_config_type == WMI_HOST_HW_MODE_DBS ||
5414+ hw_config_type == WMI_HOST_HW_MODE_DBS_OR_SBS)
5415+ dbs_mode = true;
5416+
5417+ if (ath12k_wmi_sbs_range_present(ab) &&
5418+ (hw_config_type == WMI_HOST_HW_MODE_SBS_PASSIVE ||
5419+ hw_config_type == WMI_HOST_HW_MODE_SBS ||
5420+ hw_config_type == WMI_HOST_HW_MODE_DBS_OR_SBS))
5421+ sbs_mode = true;
5422+ }
5423+ }
5424+
5425+ info->support_dbs = dbs_mode;
5426+ info->support_sbs = sbs_mode;
5427+
5428+ ath12k_wmi_dump_freq_range(ab);
5429+
5430+ return 0;
5431+}
5432+
49255433 static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,
49265434 u16 tag, u16 len,
49275435 const void *ptr, void *data)
49285436 {
5437+ const struct ath12k_wmi_dbs_or_sbs_cap_params *dbs_or_sbs_caps;
49295438 struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0];
49305439 struct ath12k_wmi_svc_rdy_ext2_parse *parse = data;
49315440 int ret;
@@ -4967,7 +5476,32 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, · 35 unmodified lines
49675476 }
49685477
49695478 parse->mac_phy_caps_ext_done = true;
5479+ } else if (!parse->hal_reg_caps_ext2_done) {
5480+ parse->hal_reg_caps_ext2_done = true;
5481+ } else if (!parse->scan_radio_caps_ext2_done) {
5482+ parse->scan_radio_caps_ext2_done = true;
5483+ } else if (!parse->twt_caps_done) {
5484+ parse->twt_caps_done = true;
5485+ } else if (!parse->htt_msdu_idx_to_qtype_map_done) {
5486+ parse->htt_msdu_idx_to_qtype_map_done = true;
5487+ } else if (!parse->dbs_or_sbs_cap_ext_done) {
5488+ dbs_or_sbs_caps = ptr;
5489+ ab->wmi_ab.sbs_lower_band_end_freq =
5490+ __le32_to_cpu(dbs_or_sbs_caps->sbs_lower_band_end_freq);
5491+
5492+ ath12k_dbg(ab, ATH12K_DBG_WMI, "sbs_lower_band_end_freq %u\n",
5493+ ab->wmi_ab.sbs_lower_band_end_freq);
5494+
5495+ ret = ath12k_wmi_update_hw_mode_list(ab);
5496+ if (ret) {
5497+ ath12k_warn(ab, "failed to update hw mode list: %d\n",
5498+ ret);
5499+ return ret;
5500+ }
5501+
5502+ parse->dbs_or_sbs_cap_ext_done = true;
49705503 }
5504+
49715505 break;
49725506 default:
49735507 break;
@@ -7626,6 +8160,64 @@ static int ath12k_wmi_pull_fw_stats(struct ath12k_base *ab, struct sk_buff *skb, · 2652 unmodified lines
76268160 &parse);
76278161 }
76288162
8163+static void ath12k_wmi_fw_stats_process(struct ath12k *ar,
8164+ struct ath12k_fw_stats *stats)
8165+{
8166+ struct ath12k_base *ab = ar->ab;
8167+ struct ath12k_pdev *pdev;
8168+ bool is_end = true;
8169+ size_t total_vdevs_started = 0;
8170+ int i;
8171+
8172+ if (stats->stats_id == WMI_REQUEST_VDEV_STAT) {
8173+ if (list_empty(&stats->vdevs)) {
8174+ ath12k_warn(ab, "empty vdev stats");
8175+ return;
8176+ }
8177+ /* FW sends all the active VDEV stats irrespective of PDEV,
8178+ * hence limit until the count of all VDEVs started
8179+ */
8180+ rcu_read_lock();
8181+ for (i = 0; i < ab->num_radios; i++) {
8182+ pdev = rcu_dereference(ab->pdevs_active[i]);
8183+ if (pdev && pdev->ar)
8184+ total_vdevs_started += pdev->ar->num_started_vdevs;
8185+ }
8186+ rcu_read_unlock();
8187+
8188+ if (total_vdevs_started)
8189+ is_end = ((++ar->fw_stats.num_vdev_recvd) ==
8190+ total_vdevs_started);
8191+
8192+ list_splice_tail_init(&stats->vdevs,
8193+ &ar->fw_stats.vdevs);
8194+
8195+ if (is_end)
8196+ complete(&ar->fw_stats_done);
8197+
8198+ return;
8199+ }
8200+
8201+ if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
8202+ if (list_empty(&stats->bcn)) {
8203+ ath12k_warn(ab, "empty beacon stats");
8204+ return;
8205+ }
8206+ /* Mark end until we reached the count of all started VDEVs
8207+ * within the PDEV
8208+ */
8209+ if (ar->num_started_vdevs)
8210+ is_end = ((++ar->fw_stats.num_bcn_recvd) ==
8211+ ar->num_started_vdevs);
8212+
8213+ list_splice_tail_init(&stats->bcn,
8214+ &ar->fw_stats.bcn);
8215+
8216+ if (is_end)
8217+ complete(&ar->fw_stats_done);
8218+ }
8219+}
8220+
76298221 static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb)
76308222 {
76318223 struct ath12k_fw_stats stats = {};
@@ -7655,19 +8247,15 @@ static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *sk · 23 unmodified lines
76558247
76568248 spin_lock_bh(&ar->data_lock);
76578249
7658− /* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via
7659− * debugfs fw stats. Therefore, processing it separately.
7660− */
8250+ /* Handle WMI_REQUEST_PDEV_STAT status update */
76618251 if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
76628252 list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs);
7663− ar->fw_stats.fw_stats_done = true;
8253+ complete(&ar->fw_stats_done);
76648254 goto complete;
76658255 }
76668256
7667− /* WMI_REQUEST_VDEV_STAT and WMI_REQUEST_BCN_STAT are currently requested only
7668− * via debugfs fw stats. Hence, processing these in debugfs context.
7669− */
7670− ath12k_debugfs_fw_stats_process(ar, &stats);
8257+ /* Handle WMI_REQUEST_VDEV_STAT and WMI_REQUEST_BCN_STAT updates. */
8258+ ath12k_wmi_fw_stats_process(ar, &stats);
76718259
76728260 complete:
76738261 complete(&ar->fw_stats_complete);
@@ -9911,3 +10499,224 @@ int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar, · 2237 unmodified lines
991110499
991210500 return 0;
991310501 }
10502+
10503+static int
10504+ath12k_wmi_fill_disallowed_bmap(struct ath12k_base *ab,
10505+ struct wmi_disallowed_mlo_mode_bitmap_params *dislw_bmap,
10506+ struct wmi_mlo_link_set_active_arg *arg)
10507+{
10508+ struct wmi_ml_disallow_mode_bmap_arg *dislw_bmap_arg;
10509+ u8 i;
10510+
10511+ if (arg->num_disallow_mode_comb >
10512+ ARRAY_SIZE(arg->disallow_bmap)) {
10513+ ath12k_warn(ab, "invalid num_disallow_mode_comb: %d",
10514+ arg->num_disallow_mode_comb);
10515+ return -EINVAL;
10516+ }
10517+
10518+ dislw_bmap_arg = &arg->disallow_bmap[0];
10519+ for (i = 0; i < arg->num_disallow_mode_comb; i++) {
10520+ dislw_bmap->tlv_header =
10521+ ath12k_wmi_tlv_cmd_hdr(0, sizeof(*dislw_bmap));
10522+ dislw_bmap->disallowed_mode_bitmap =
10523+ cpu_to_le32(dislw_bmap_arg->disallowed_mode);
10524+ dislw_bmap->ieee_link_id_comb =
10525+ le32_encode_bits(dislw_bmap_arg->ieee_link_id[0],
10526+ WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_1) |
10527+ le32_encode_bits(dislw_bmap_arg->ieee_link_id[1],
10528+ WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_2) |
10529+ le32_encode_bits(dislw_bmap_arg->ieee_link_id[2],
10530+ WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_3) |
10531+ le32_encode_bits(dislw_bmap_arg->ieee_link_id[3],
10532+ WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_4);
10533+
10534+ ath12k_dbg(ab, ATH12K_DBG_WMI,
10535+ "entry %d disallowed_mode %d ieee_link_id_comb 0x%x",
10536+ i, dislw_bmap_arg->disallowed_mode,
10537+ dislw_bmap_arg->ieee_link_id_comb);
10538+ dislw_bmap++;
10539+ dislw_bmap_arg++;
10540+ }
10541+
10542+ return 0;
10543+}
10544+
10545+int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
10546+ struct wmi_mlo_link_set_active_arg *arg)
10547+{
10548+ struct wmi_disallowed_mlo_mode_bitmap_params *disallowed_mode_bmap;
10549+ struct wmi_mlo_set_active_link_number_params *link_num_param;
10550+ u32 num_link_num_param = 0, num_vdev_bitmap = 0;
10551+ struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;
10552+ struct wmi_mlo_link_set_active_cmd *cmd;
10553+ u32 num_inactive_vdev_bitmap = 0;
10554+ u32 num_disallow_mode_comb = 0;
10555+ struct wmi_tlv *tlv;
10556+ struct sk_buff *skb;
10557+ __le32 *vdev_bitmap;
10558+ void *buf_ptr;
10559+ int i, ret;
10560+ u32 len;
10561+
10562+ if (!arg->num_vdev_bitmap && !arg->num_link_entry) {
10563+ ath12k_warn(ab, "Invalid num_vdev_bitmap and num_link_entry");
10564+ return -EINVAL;
10565+ }
10566+
10567+ switch (arg->force_mode) {
10568+ case WMI_MLO_LINK_FORCE_MODE_ACTIVE_LINK_NUM:
10569+ case WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM:
10570+ num_link_num_param = arg->num_link_entry;
10571+ fallthrough;
10572+ case WMI_MLO_LINK_FORCE_MODE_ACTIVE:
10573+ case WMI_MLO_LINK_FORCE_MODE_INACTIVE:
10574+ case WMI_MLO_LINK_FORCE_MODE_NO_FORCE:
10575+ num_vdev_bitmap = arg->num_vdev_bitmap;
10576+ break;
10577+ case WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE:
10578+ num_vdev_bitmap = arg->num_vdev_bitmap;
10579+ num_inactive_vdev_bitmap = arg->num_inactive_vdev_bitmap;
10580+ break;
10581+ default:
10582+ ath12k_warn(ab, "Invalid force mode: %u", arg->force_mode);
10583+ return -EINVAL;
10584+ }
10585+
10586+ num_disallow_mode_comb = arg->num_disallow_mode_comb;
10587+ len = sizeof(*cmd) +
10588+ TLV_HDR_SIZE + sizeof(*link_num_param) * num_link_num_param +
10589+ TLV_HDR_SIZE + sizeof(*vdev_bitmap) * num_vdev_bitmap +
10590+ TLV_HDR_SIZE + TLV_HDR_SIZE + TLV_HDR_SIZE +
10591+ TLV_HDR_SIZE + sizeof(*disallowed_mode_bmap) * num_disallow_mode_comb;
10592+ if (arg->force_mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE)
10593+ len += sizeof(*vdev_bitmap) * num_inactive_vdev_bitmap;
10594+
10595+ skb = ath12k_wmi_alloc_skb(wmi_ab, len);
10596+ if (!skb)
10597+ return -ENOMEM;
10598+
10599+ cmd = (struct wmi_mlo_link_set_active_cmd *)skb->data;
10600+ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MLO_LINK_SET_ACTIVE_CMD,
10601+ sizeof(*cmd));
10602+ cmd->force_mode = cpu_to_le32(arg->force_mode);
10603+ cmd->reason = cpu_to_le32(arg->reason);
10604+ ath12k_dbg(ab, ATH12K_DBG_WMI,
10605+ "mode %d reason %d num_link_num_param %d num_vdev_bitmap %d inactive %d num_disallow_mode_comb %d",
10606+ arg->force_mode, arg->reason, num_link_num_param,
10607+ num_vdev_bitmap, num_inactive_vdev_bitmap,
10608+ num_disallow_mode_comb);
10609+
10610+ buf_ptr = skb->data + sizeof(*cmd);
10611+ tlv = buf_ptr;
10612+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
10613+ sizeof(*link_num_param) * num_link_num_param);
10614+ buf_ptr += TLV_HDR_SIZE;
10615+
10616+ if (num_link_num_param) {
10617+ cmd->ctrl_flags =
10618+ le32_encode_bits(arg->ctrl_flags.dync_force_link_num ? 1 : 0,
10619+ CRTL_F_DYNC_FORCE_LINK_NUM);
10620+
10621+ link_num_param = buf_ptr;
10622+ for (i = 0; i < num_link_num_param; i++) {
10623+ link_num_param->tlv_header =
10624+ ath12k_wmi_tlv_cmd_hdr(0, sizeof(*link_num_param));
10625+ link_num_param->num_of_link =
10626+ cpu_to_le32(arg->link_num[i].num_of_link);
10627+ link_num_param->vdev_type =
10628+ cpu_to_le32(arg->link_num[i].vdev_type);
10629+ link_num_param->vdev_subtype =
10630+ cpu_to_le32(arg->link_num[i].vdev_subtype);
10631+ link_num_param->home_freq =
10632+ cpu_to_le32(arg->link_num[i].home_freq);
10633+ ath12k_dbg(ab, ATH12K_DBG_WMI,
10634+ "entry %d num_of_link %d vdev type %d subtype %d freq %d control_flags %d",
10635+ i, arg->link_num[i].num_of_link,
10636+ arg->link_num[i].vdev_type,
10637+ arg->link_num[i].vdev_subtype,
10638+ arg->link_num[i].home_freq,
10639+ __le32_to_cpu(cmd->ctrl_flags));
10640+ link_num_param++;
10641+ }
10642+
10643+ buf_ptr += sizeof(*link_num_param) * num_link_num_param;
10644+ }
10645+
10646+ tlv = buf_ptr;
10647+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32,
10648+ sizeof(*vdev_bitmap) * num_vdev_bitmap);
10649+ buf_ptr += TLV_HDR_SIZE;
10650+
10651+ if (num_vdev_bitmap) {
10652+ vdev_bitmap = buf_ptr;
10653+ for (i = 0; i < num_vdev_bitmap; i++) {
10654+ vdev_bitmap[i] = cpu_to_le32(arg->vdev_bitmap[i]);
10655+ ath12k_dbg(ab, ATH12K_DBG_WMI, "entry %d vdev_id_bitmap 0x%x",
10656+ i, arg->vdev_bitmap[i]);
10657+ }
10658+
10659+ buf_ptr += sizeof(*vdev_bitmap) * num_vdev_bitmap;
10660+ }
10661+
10662+ if (arg->force_mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE) {
10663+ tlv = buf_ptr;
10664+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32,
10665+ sizeof(*vdev_bitmap) *
10666+ num_inactive_vdev_bitmap);
10667+ buf_ptr += TLV_HDR_SIZE;
10668+
10669+ if (num_inactive_vdev_bitmap) {
10670+ vdev_bitmap = buf_ptr;
10671+ for (i = 0; i < num_inactive_vdev_bitmap; i++) {
10672+ vdev_bitmap[i] =
10673+ cpu_to_le32(arg->inactive_vdev_bitmap[i]);
10674+ ath12k_dbg(ab, ATH12K_DBG_WMI,
10675+ "entry %d inactive_vdev_id_bitmap 0x%x",
10676+ i, arg->inactive_vdev_bitmap[i]);
10677+ }
10678+
10679+ buf_ptr += sizeof(*vdev_bitmap) * num_inactive_vdev_bitmap;
10680+ }
10681+ } else {
10682+ /* add empty vdev bitmap2 tlv */
10683+ tlv = buf_ptr;
10684+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0);
10685+ buf_ptr += TLV_HDR_SIZE;
10686+ }
10687+
10688+ /* add empty ieee_link_id_bitmap tlv */
10689+ tlv = buf_ptr;
10690+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0);
10691+ buf_ptr += TLV_HDR_SIZE;
10692+
10693+ /* add empty ieee_link_id_bitmap2 tlv */
10694+ tlv = buf_ptr;
10695+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0);
10696+ buf_ptr += TLV_HDR_SIZE;
10697+
10698+ tlv = buf_ptr;
10699+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
10700+ sizeof(*disallowed_mode_bmap) *
10701+ arg->num_disallow_mode_comb);
10702+ buf_ptr += TLV_HDR_SIZE;
10703+
10704+ ret = ath12k_wmi_fill_disallowed_bmap(ab, buf_ptr, arg);
10705+ if (ret)
10706+ goto free_skb;
10707+
10708+ ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0], skb, WMI_MLO_LINK_SET_ACTIVE_CMDID);
10709+ if (ret) {
10710+ ath12k_warn(ab,
10711+ "failed to send WMI_MLO_LINK_SET_ACTIVE_CMDID: %d\n", ret);
10712+ goto free_skb;
10713+ }
10714+
10715+ ath12k_dbg(ab, ATH12K_DBG_WMI, "WMI mlo link set active cmd");
10716+
10717+ return ret;
10718+
10719+free_skb:
10720+ dev_kfree_skb(skb);
10721+ return ret;
10722+}
drivers/net/wireless/ath/ath12k/wmi.h+179−1
@@ -1974,6 +1974,7 @@ enum wmi_tlv_tag { · 1973 unmodified lines
19741974 WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT,
19751975 WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5,
19761976 WMI_TAG_VDEV_CH_POWER_INFO,
1977+ WMI_TAG_MLO_LINK_SET_ACTIVE_CMD = 0x3BE,
19771978 WMI_TAG_EHT_RATE_SET = 0x3C4,
19781979 WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5,
19791980 WMI_TAG_MLO_TX_SEND_PARAMS,
@@ -2617,6 +2618,8 @@ struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params { · 637 unmodified lines
26172618 __le32 num_chainmask_tables;
26182619 } __packed;
26192620
2621+#define WMI_HW_MODE_CAP_CFG_TYPE GENMASK(27, 0)
2622+
26202623 struct ath12k_wmi_hw_mode_cap_params {
26212624 __le32 tlv_header;
26222625 __le32 hw_mode_id;
@@ -2666,6 +2669,12 @@ struct ath12k_wmi_mac_phy_caps_params { · 43 unmodified lines
26662669 __le32 he_cap_info_2g_ext;
26672670 __le32 he_cap_info_5g_ext;
26682671 __le32 he_cap_info_internal;
2672+ __le32 wireless_modes;
2673+ __le32 low_2ghz_chan_freq;
2674+ __le32 high_2ghz_chan_freq;
2675+ __le32 low_5ghz_chan_freq;
2676+ __le32 high_5ghz_chan_freq;
2677+ __le32 nss_ratio;
26692678 } __packed;
26702679
26712680 struct ath12k_wmi_hal_reg_caps_ext_params {
@@ -2739,6 +2748,11 @@ struct wmi_service_ready_ext2_event { · 67 unmodified lines
27392748 __le32 default_num_msduq_supported_per_tid;
27402749 } __packed;
27412750
2751+struct ath12k_wmi_dbs_or_sbs_cap_params {
2752+ __le32 hw_mode_id;
2753+ __le32 sbs_lower_band_end_freq;
2754+} __packed;
2755+
27422756 struct ath12k_wmi_caps_ext_params {
27432757 __le32 hw_mode_id;
27442758 __le32 pdev_and_hw_link_ids;
@@ -5049,6 +5063,53 @@ struct ath12k_wmi_pdev { · 2304 unmodified lines
50495063 u32 rx_decap_mode;
50505064 };
50515065
5066+struct ath12k_hw_mode_freq_range_arg {
5067+ u32 low_2ghz_freq;
5068+ u32 high_2ghz_freq;
5069+ u32 low_5ghz_freq;
5070+ u32 high_5ghz_freq;
5071+};
5072+
5073+struct ath12k_svc_ext_mac_phy_info {
5074+ enum wmi_host_hw_mode_config_type hw_mode_config_type;
5075+ u32 phy_id;
5076+ u32 supported_bands;
5077+ struct ath12k_hw_mode_freq_range_arg hw_freq_range;
5078+};
5079+
5080+#define ATH12K_MAX_MAC_PHY_CAP 8
5081+
5082+struct ath12k_svc_ext_info {
5083+ u32 num_hw_modes;
5084+ struct ath12k_svc_ext_mac_phy_info mac_phy_info[ATH12K_MAX_MAC_PHY_CAP];
5085+};
5086+
5087+/**
5088+ * enum ath12k_hw_mode - enum for host mode
5089+ * @ATH12K_HW_MODE_SMM: Single mac mode
5090+ * @ATH12K_HW_MODE_DBS: DBS mode
5091+ * @ATH12K_HW_MODE_SBS: SBS mode with either high share or low share
5092+ * @ATH12K_HW_MODE_SBS_UPPER_SHARE: Higher 5 GHz shared with 2.4 GHz
5093+ * @ATH12K_HW_MODE_SBS_LOWER_SHARE: Lower 5 GHz shared with 2.4 GHz
5094+ * @ATH12K_HW_MODE_MAX: Max, used to indicate invalid mode
5095+ */
5096+enum ath12k_hw_mode {
5097+ ATH12K_HW_MODE_SMM,
5098+ ATH12K_HW_MODE_DBS,
5099+ ATH12K_HW_MODE_SBS,
5100+ ATH12K_HW_MODE_SBS_UPPER_SHARE,
5101+ ATH12K_HW_MODE_SBS_LOWER_SHARE,
5102+ ATH12K_HW_MODE_MAX,
5103+};
5104+
5105+struct ath12k_hw_mode_info {
5106+ bool support_dbs:1;
5107+ bool support_sbs:1;
5108+
5109+ struct ath12k_hw_mode_freq_range_arg freq_range_caps[ATH12K_HW_MODE_MAX]
5110+ [MAX_RADIOS];
5111+};
5112+
50525113 struct ath12k_wmi_base {
50535114 struct ath12k_base *ab;
50545115 struct ath12k_wmi_pdev wmi[MAX_RADIOS];
@@ -5066,6 +5127,10 @@ struct ath12k_wmi_base { · 11 unmodified lines
50665127 enum wmi_host_hw_mode_config_type preferred_hw_mode;
50675128
50685129 struct ath12k_wmi_target_cap_arg *targ_cap;
5130+
5131+ struct ath12k_svc_ext_info svc_ext_info;
5132+ u32 sbs_lower_band_end_freq;
5133+ struct ath12k_hw_mode_info hw_mode_info;
50695134 };
50705135
50715136 struct wmi_pdev_set_bios_interface_cmd {
@@ -5997,6 +6062,118 @@ struct wmi_vdev_set_tpc_power_cmd { · 925 unmodified lines
59976062 */
59986063 } __packed;
59996064
6065+#define CRTL_F_DYNC_FORCE_LINK_NUM GENMASK(3, 2)
6066+
6067+struct wmi_mlo_link_set_active_cmd {
6068+ __le32 tlv_header;
6069+ __le32 force_mode;
6070+ __le32 reason;
6071+ __le32 use_ieee_link_id_bitmap;
6072+ struct ath12k_wmi_mac_addr_params ap_mld_mac_addr;
6073+ __le32 ctrl_flags;
6074+} __packed;
6075+
6076+struct wmi_mlo_set_active_link_number_params {
6077+ __le32 tlv_header;
6078+ __le32 num_of_link;
6079+ __le32 vdev_type;
6080+ __le32 vdev_subtype;
6081+ __le32 home_freq;
6082+} __packed;
6083+
6084+#define WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_1 GENMASK(7, 0)
6085+#define WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_2 GENMASK(15, 8)
6086+#define WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_3 GENMASK(23, 16)
6087+#define WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_4 GENMASK(31, 24)
6088+
6089+struct wmi_disallowed_mlo_mode_bitmap_params {
6090+ __le32 tlv_header;
6091+ __le32 disallowed_mode_bitmap;
6092+ __le32 ieee_link_id_comb;
6093+} __packed;
6094+
6095+enum wmi_mlo_link_force_mode {
6096+ WMI_MLO_LINK_FORCE_MODE_ACTIVE = 1,
6097+ WMI_MLO_LINK_FORCE_MODE_INACTIVE = 2,
6098+ WMI_MLO_LINK_FORCE_MODE_ACTIVE_LINK_NUM = 3,
6099+ WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM = 4,
6100+ WMI_MLO_LINK_FORCE_MODE_NO_FORCE = 5,
6101+ WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE = 6,
6102+ WMI_MLO_LINK_FORCE_MODE_NON_FORCE_UPDATE = 7,
6103+};
6104+
6105+enum wmi_mlo_link_force_reason {
6106+ WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT = 1,
6107+ WMI_MLO_LINK_FORCE_REASON_NEW_DISCONNECT = 2,
6108+ WMI_MLO_LINK_FORCE_REASON_LINK_REMOVAL = 3,
6109+ WMI_MLO_LINK_FORCE_REASON_TDLS = 4,
6110+ WMI_MLO_LINK_FORCE_REASON_REVERT_FAILURE = 5,
6111+ WMI_MLO_LINK_FORCE_REASON_LINK_DELETE = 6,
6112+ WMI_MLO_LINK_FORCE_REASON_SINGLE_LINK_EMLSR_OP = 7,
6113+};
6114+
6115+struct wmi_mlo_link_num_arg {
6116+ u32 num_of_link;
6117+ u32 vdev_type;
6118+ u32 vdev_subtype;
6119+ u32 home_freq;
6120+};
6121+
6122+struct wmi_mlo_control_flags_arg {
6123+ bool overwrite_force_active_bitmap;
6124+ bool overwrite_force_inactive_bitmap;
6125+ bool dync_force_link_num;
6126+ bool post_re_evaluate;
6127+ u8 post_re_evaluate_loops;
6128+ bool dont_reschedule_workqueue;
6129+};
6130+
6131+struct wmi_ml_link_force_cmd_arg {
6132+ u8 ap_mld_mac_addr[ETH_ALEN];
6133+ u16 ieee_link_id_bitmap;
6134+ u16 ieee_link_id_bitmap2;
6135+ u8 link_num;
6136+};
6137+
6138+struct wmi_ml_disallow_mode_bmap_arg {
6139+ u32 disallowed_mode;
6140+ union {
6141+ u32 ieee_link_id_comb;
6142+ u8 ieee_link_id[4];
6143+ };
6144+};
6145+
6146+/* maximum size of link number param array
6147+ * for MLO link set active command
6148+ */
6149+#define WMI_MLO_LINK_NUM_SZ 2
6150+
6151+/* maximum size of vdev bitmap array for
6152+ * MLO link set active command
6153+ */
6154+#define WMI_MLO_VDEV_BITMAP_SZ 2
6155+
6156+/* Max number of disallowed bitmap combination
6157+ * sent to firmware
6158+ */
6159+#define WMI_ML_MAX_DISALLOW_BMAP_COMB 4
6160+
6161+struct wmi_mlo_link_set_active_arg {
6162+ enum wmi_mlo_link_force_mode force_mode;
6163+ enum wmi_mlo_link_force_reason reason;
6164+ u32 num_link_entry;
6165+ u32 num_vdev_bitmap;
6166+ u32 num_inactive_vdev_bitmap;
6167+ struct wmi_mlo_link_num_arg link_num[WMI_MLO_LINK_NUM_SZ];
6168+ u32 vdev_bitmap[WMI_MLO_VDEV_BITMAP_SZ];
6169+ u32 inactive_vdev_bitmap[WMI_MLO_VDEV_BITMAP_SZ];
6170+ struct wmi_mlo_control_flags_arg ctrl_flags;
6171+ bool use_ieee_link_id;
6172+ struct wmi_ml_link_force_cmd_arg force_cmd;
6173+ u32 num_disallow_mode_comb;
6174+ struct wmi_ml_disallow_mode_bmap_arg disallow_bmap[WMI_ML_MAX_DISALLOW_BMAP_COMB];
6175+};
6176+
60006177 void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
60016178 struct ath12k_wmi_resource_config_arg *config);
60026179 void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,
@@ -6195,5 +6372,6 @@ bool ath12k_wmi_supports_6ghz_cc_ext(struct ath12k *ar); · 192 unmodified lines
61956372 int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar,
61966373 u32 vdev_id,
61976374 struct ath12k_reg_tpc_power_info *param);
6198−
6375+int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
6376+ struct wmi_mlo_link_set_active_arg *param);
61996377 #endif
drivers/net/wireless/ath/ath6kl/bmi.c+3−1
@@ -87,7 +87,9 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, · 86 unmodified lines
8787 * We need to do some backwards compatibility to make this work.
8888 */
8989 if (le32_to_cpu(targ_info->byte_count) != sizeof(*targ_info)) {
90− WARN_ON(1);
90+ ath6kl_err("mismatched byte count %d vs. expected %zd\n",
91+ le32_to_cpu(targ_info->byte_count),
92+ sizeof(*targ_info));
9193 return -EINVAL;
9294 }
9395
drivers/net/wireless/ath/carl9170/usb.c+13−6
@@ -438,14 +438,21 @@ static void carl9170_usb_rx_complete(struct urb *urb) · 437 unmodified lines
438438
439439 if (atomic_read(&ar->rx_anch_urbs) == 0) {
440440 /*
441− * The system is too slow to cope with
442− * the enormous workload. We have simply
443− * run out of active rx urbs and this
444− * unfortunately leads to an unpredictable
445− * device.
441+ * At this point, either the system is too slow to
442+ * cope with the enormous workload (so we have simply
443+ * run out of active rx urbs and this unfortunately
444+ * leads to an unpredictable device), or the device
445+ * is not fully functional after an unsuccessful
446+ * firmware loading attempts (so it doesn't pass
447+ * ieee80211_register_hw() and there is no internal
448+ * workqueue at all).
446449 */
447450
448− ieee80211_queue_work(ar->hw, &ar->ping_work);
451+ if (ar->registered)
452+ ieee80211_queue_work(ar->hw, &ar->ping_work);
453+ else
454+ pr_warn_once("device %s is not registered\n",
455+ dev_name(&ar->udev->dev));
449456 }
450457 } else {
451458 /*
drivers/net/wireless/intel/iwlwifi/dvm/main.c+1−0
@@ -1316,6 +1316,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, · 1315 unmodified lines
13161316 sizeof(trans->conf.no_reclaim_cmds));
13171317 memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,
13181318 sizeof(no_reclaim_cmds));
1319+ trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
13191320
13201321 switch (iwlwifi_mod_params.amsdu_size) {
13211322 case IWL_AMSDU_DEF:
drivers/net/wireless/intel/iwlwifi/mld/mld.c+1−0
@@ -77,6 +77,7 @@ void iwl_construct_mld(struct iwl_mld *mld, struct iwl_trans *trans, · 76 unmodified lines
7777
7878 /* Setup async RX handling */
7979 spin_lock_init(&mld->async_handlers_lock);
80+ INIT_LIST_HEAD(&mld->async_handlers_list);
8081 wiphy_work_init(&mld->async_handlers_wk,
8182 iwl_mld_async_handlers_wk);
8283
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c+1−1
@@ -34,7 +34,7 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm, · 33 unmodified lines
3434 WIDE_ID(MAC_CONF_GROUP,
3535 MAC_CONFIG_CMD), 0);
3636
37− if (WARN_ON(cmd_ver < 1 && cmd_ver > 3))
37+ if (WARN_ON(cmd_ver < 1 || cmd_ver > 3))
3838 return;
3939
4040 cmd->id_and_color = cpu_to_le32(mvmvif->id);
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c+6−5
@@ -166,7 +166,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, · 165 unmodified lines
166166 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
167167 struct iwl_context_info *ctxt_info;
168168 struct iwl_context_info_rbd_cfg *rx_cfg;
169− u32 control_flags = 0, rb_size;
169+ u32 control_flags = 0, rb_size, cb_size;
170170 dma_addr_t phys;
171171 int ret;
172172
@@ -202,11 +202,12 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, · 29 unmodified lines
202202 rb_size = IWL_CTXT_INFO_RB_SIZE_4K;
203203 }
204204
205− WARN_ON(RX_QUEUE_CB_SIZE(iwl_trans_get_num_rbds(trans)) > 12);
205+ cb_size = RX_QUEUE_CB_SIZE(iwl_trans_get_num_rbds(trans));
206+ if (WARN_ON(cb_size > 12))
207+ cb_size = 12;
208+
206209 control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG;
207− control_flags |=
208− u32_encode_bits(RX_QUEUE_CB_SIZE(iwl_trans_get_num_rbds(trans)),
209− IWL_CTXT_INFO_RB_CB_SIZE);
210+ control_flags |= u32_encode_bits(cb_size, IWL_CTXT_INFO_RB_CB_SIZE);
210211 control_flags |= u32_encode_bits(rb_size, IWL_CTXT_INFO_RB_SIZE);
211212 ctxt_info->control.control_flags = cpu_to_le32(control_flags);
212213
include/linux/ieee80211.h+9−9
@@ -1278,7 +1278,7 @@ struct ieee80211_ext { · 1277 unmodified lines
12781278 u8 sa[ETH_ALEN];
12791279 __le32 timestamp;
12801280 u8 change_seq;
1281− u8 variable[0];
1281+ u8 variable[];
12821282 } __packed s1g_beacon;
12831283 } u;
12841284 } __packed __aligned(2);
@@ -1536,7 +1536,7 @@ struct ieee80211_mgmt { · 251 unmodified lines
15361536 u8 action_code;
15371537 u8 dialog_token;
15381538 __le16 capability;
1539− u8 variable[0];
1539+ u8 variable[];
15401540 } __packed tdls_discover_resp;
15411541 struct {
15421542 u8 action_code;
@@ -1721,35 +1721,35 @@ struct ieee80211_tdls_data { · 178 unmodified lines
17211721 struct {
17221722 u8 dialog_token;
17231723 __le16 capability;
1724− u8 variable[0];
1724+ u8 variable[];
17251725 } __packed setup_req;
17261726 struct {
17271727 __le16 status_code;
17281728 u8 dialog_token;
17291729 __le16 capability;
1730− u8 variable[0];
1730+ u8 variable[];
17311731 } __packed setup_resp;
17321732 struct {
17331733 __le16 status_code;
17341734 u8 dialog_token;
1735− u8 variable[0];
1735+ u8 variable[];
17361736 } __packed setup_cfm;
17371737 struct {
17381738 __le16 reason_code;
1739− u8 variable[0];
1739+ u8 variable[];
17401740 } __packed teardown;
17411741 struct {
17421742 u8 dialog_token;
1743− u8 variable[0];
1743+ u8 variable[];
17441744 } __packed discover_req;
17451745 struct {
17461746 u8 target_channel;
17471747 u8 oper_class;
1748− u8 variable[0];
1748+ u8 variable[];
17491749 } __packed chan_switch_req;
17501750 struct {
17511751 __le16 status_code;
1752− u8 variable[0];
1752+ u8 variable[];
17531753 } __packed chan_switch_resp;
17541754 } u;
17551755 } __packed;
net/mac80211/debug.h+4−1
@@ -1,10 +1,11 @@
11 /* SPDX-License-Identifier: GPL-2.0 */
22 /*
33 * Portions
4− * Copyright (C) 2022 - 2024 Intel Corporation
4+ * Copyright (C) 2022 - 2025 Intel Corporation
55 */
66 #ifndef __MAC80211_DEBUG_H
77 #define __MAC80211_DEBUG_H
8+#include <linux/once_lite.h>
89 #include <net/cfg80211.h>
910
1011 #ifdef CONFIG_MAC80211_OCB_DEBUG
@@ -152,6 +153,8 @@ do { \ · 141 unmodified lines
152153 else \
153154 _sdata_err((link)->sdata, fmt, ##__VA_ARGS__); \
154155 } while (0)
156+#define link_err_once(link, fmt, ...) \
157+ DO_ONCE_LITE(link_err, link, fmt, ##__VA_ARGS__)
155158 #define link_id_info(sdata, link_id, fmt, ...) \
156159 do { \
157160 if (ieee80211_vif_is_mld(&sdata->vif)) \
net/mac80211/rx.c+4−0
@@ -4432,6 +4432,10 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) · 4431 unmodified lines
44324432 if (!multicast &&
44334433 !ether_addr_equal(sdata->dev->dev_addr, hdr->addr1))
44344434 return false;
4435+ /* reject invalid/our STA address */
4436+ if (!is_valid_ether_addr(hdr->addr2) ||
4437+ ether_addr_equal(sdata->dev->dev_addr, hdr->addr2))
4438+ return false;
44354439 if (!rx->sta) {
44364440 int rate_idx;
44374441 if (status->encoding != RX_ENC_LEGACY)
net/mac80211/tx.c+21−8
@@ -5,7 +5,7 @@ · 4 unmodified lines
55 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
66 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
77 * Copyright 2013-2014 Intel Mobile Communications GmbH
8− * Copyright (C) 2018-2024 Intel Corporation
8+ * Copyright (C) 2018-2025 Intel Corporation
99 *
1010 * Transmit and frame generation functions.
1111 */
@@ -5016,12 +5016,25 @@ static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata, · 5004 unmodified lines
50165016 }
50175017 }
50185018
5019−static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon)
5019+static u8 __ieee80211_beacon_update_cntdwn(struct ieee80211_link_data *link,
5020+ struct beacon_data *beacon)
50205021 {
5021− beacon->cntdwn_current_counter--;
5022+ if (beacon->cntdwn_current_counter == 1) {
5023+ /*
5024+ * Channel switch handling is done by a worker thread while
5025+ * beacons get pulled from hardware timers. It's therefore
5026+ * possible that software threads are slow enough to not be
5027+ * able to complete CSA handling in a single beacon interval,
5028+ * in which case we get here. There isn't much to do about
5029+ * it, other than letting the user know that the AP isn't
5030+ * behaving correctly.
5031+ */
5032+ link_err_once(link,
5033+ "beacon TX faster than countdown (channel/color switch) completion\n");
5034+ return 0;
5035+ }
50225036
5023− /* the counter should never reach 0 */
5024− WARN_ON_ONCE(!beacon->cntdwn_current_counter);
5037+ beacon->cntdwn_current_counter--;
50255038
50265039 return beacon->cntdwn_current_counter;
50275040 }
@@ -5052,7 +5065,7 @@ u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif, unsigned int link_i · 24 unmodified lines
50525065 if (!beacon)
50535066 goto unlock;
50545067
5055− count = __ieee80211_beacon_update_cntdwn(beacon);
5068+ count = __ieee80211_beacon_update_cntdwn(link, beacon);
50565069
50575070 unlock:
50585071 rcu_read_unlock();
@@ -5450,7 +5463,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, · 391 unmodified lines
54505463
54515464 if (beacon->cntdwn_counter_offsets[0]) {
54525465 if (!is_template)
5453− __ieee80211_beacon_update_cntdwn(beacon);
5466+ __ieee80211_beacon_update_cntdwn(link, beacon);
54545467
54555468 ieee80211_set_beacon_cntdwn(sdata, beacon, link);
54565469 }
@@ -5482,7 +5495,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, · 25 unmodified lines
54825495 * for now we leave it consistent with overall
54835496 * mac80211's behavior.
54845497 */
5485− __ieee80211_beacon_update_cntdwn(beacon);
5498+ __ieee80211_beacon_update_cntdwn(link, beacon);
54865499
54875500 ieee80211_set_beacon_cntdwn(sdata, beacon, link);
54885501 }