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
1216 INIT_LIST_HEAD(&ar->fw_stats.pdevs);1216 INIT_LIST_HEAD(&ar->fw_stats.pdevs);
1217 INIT_LIST_HEAD(&ar->fw_stats.bcn);1217 INIT_LIST_HEAD(&ar->fw_stats.bcn);
1218 init_completion(&ar->fw_stats_complete);1218 init_completion(&ar->fw_stats_complete);
1219 init_completion(&ar->fw_stats_done);
1219}1220}
1220 1221
1221void ath12k_fw_stats_free(struct ath12k_fw_stats *stats)1222void 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
1228void ath12k_fw_stats_reset(struct ath12k *ar)1229void ath12k_fw_stats_reset(struct ath12k *ar)
1229{1230{
1230 spin_lock_bh(&ar->data_lock);1231 spin_lock_bh(&ar->data_lock);
1231 ar->fw_stats.fw_stats_done = false;
1232 ath12k_fw_stats_free(&ar->fw_stats);1232 ath12k_fw_stats_free(&ar->fw_stats);
1233 ar->fw_stats.num_vdev_recvd = 0;
1234 ar->fw_stats.num_bcn_recvd = 0;
1233 spin_unlock_bh(&ar->data_lock);1235 spin_unlock_bh(&ar->data_lock);
1234}1236}
1235 1237
drivers/net/wireless/ath/ath12k/core.h+9−1
@@ -601,6 +601,12 @@ struct ath12k_sta { · 600 unmodified lines
601#define ATH12K_NUM_CHANS 101601#define ATH12K_NUM_CHANS 101
602#define ATH12K_MAX_5GHZ_CHAN 173602#define ATH12K_MAX_5GHZ_CHAN 173
603 603
604static 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
604enum ath12k_hw_state {610enum ath12k_hw_state {
605 ATH12K_HW_STATE_OFF,611 ATH12K_HW_STATE_OFF,
606 ATH12K_HW_STATE_ON,612 ATH12K_HW_STATE_ON,
@@ -626,7 +632,8 @@ struct ath12k_fw_stats { · 19 unmodified lines
626 struct list_head pdevs;632 struct list_head pdevs;
627 struct list_head vdevs;633 struct list_head vdevs;
628 struct list_head bcn;634 struct list_head bcn;
629 bool fw_stats_done;635 u32 num_vdev_recvd;
636 u32 num_bcn_recvd;
630};637};
631 638
632struct ath12k_dbg_htt_stats {639struct ath12k_dbg_htt_stats {
@@ -806,6 +813,7 @@ struct ath12k { · 173 unmodified lines
806 bool regdom_set_by_user;813 bool regdom_set_by_user;
807 814
808 struct completion fw_stats_complete;815 struct completion fw_stats_complete;
816 struct completion fw_stats_done;
809 817
810 struct completion mlo_setup_done;818 struct completion mlo_setup_done;
811 u32 mlo_setup_status;819 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
1251 */1251 */
1252}1252}
1253 1253
1254void
1255ath12k_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
1312static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)1254static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)
1313{1255{
1314 struct ath12k *ar = inode->i_private;1256 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
12void ath12k_debugfs_soc_destroy(struct ath12k_base *ab);12void ath12k_debugfs_soc_destroy(struct ath12k_base *ab);
13void ath12k_debugfs_register(struct ath12k *ar);13void ath12k_debugfs_register(struct ath12k *ar);
14void ath12k_debugfs_unregister(struct ath12k *ar);14void ath12k_debugfs_unregister(struct ath12k *ar);
15void ath12k_debugfs_fw_stats_process(struct ath12k *ar,
16 struct ath12k_fw_stats *stats);
17void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,15void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
18 struct ieee80211_vif *vif);16 struct ieee80211_vif *vif);
19void ath12k_debugfs_pdev_create(struct ath12k_base *ab);17void ath12k_debugfs_pdev_create(struct ath12k_base *ab);
@@ -126,11 +124,6 @@ static inline void ath12k_debugfs_unregister(struct ath12k *ar) · 106 unmodified lines
126{124{
127}125}
128 126
129static inline void ath12k_debugfs_fw_stats_process(struct ath12k *ar,
130 struct ath12k_fw_stats *stats)
131{
132}
133
134static inline bool ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar)127static inline bool ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar)
135{128{
136 return false;129 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
4360{4360{
4361 struct ath12k_base *ab = ar->ab;4361 struct ath12k_base *ab = ar->ab;
4362 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);4362 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
4363 unsigned long timeout, time_left;4363 unsigned long time_left;
4364 int ret;4364 int ret;
4365 4365
4366 guard(mutex)(&ah->hw_mutex);4366 guard(mutex)(&ah->hw_mutex);
@@ -4368,19 +4368,13 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar, · 1 unmodified line
4368 if (ah->state != ATH12K_HW_STATE_ON)4368 if (ah->state != ATH12K_HW_STATE_ON)
4369 return -ENETDOWN;4369 return -ENETDOWN;
4370 4370
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);
4377 ath12k_fw_stats_reset(ar);4371 ath12k_fw_stats_reset(ar);
4378 4372
4379 reinit_completion(&ar->fw_stats_complete);4373 reinit_completion(&ar->fw_stats_complete);
4374 reinit_completion(&ar->fw_stats_done);
4380 4375
4381 ret = ath12k_wmi_send_stats_request_cmd(ar, param->stats_id,4376 ret = ath12k_wmi_send_stats_request_cmd(ar, param->stats_id,
4382 param->vdev_id, param->pdev_id);4377 param->vdev_id, param->pdev_id);
4383
4384 if (ret) {4378 if (ret) {
4385 ath12k_warn(ab, "failed to request fw stats: %d\n", ret);4379 ath12k_warn(ab, "failed to request fw stats: %d\n", ret);
4386 return ret;4380 return ret;
@@ -4391,7 +4385,6 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar, · 4 unmodified lines
4391 param->pdev_id, param->vdev_id, param->stats_id);4385 param->pdev_id, param->vdev_id, param->stats_id);
4392 4386
4393 time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);4387 time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
4394
4395 if (!time_left) {4388 if (!time_left) {
4396 ath12k_warn(ab, "time out while waiting for get fw stats\n");4389 ath12k_warn(ab, "time out while waiting for get fw stats\n");
4397 return -ETIMEDOUT;4390 return -ETIMEDOUT;
@@ -4400,20 +4393,15 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar, · 2 unmodified lines
4400 /* Firmware sends WMI_UPDATE_STATS_EVENTID back-to-back4393 /* Firmware sends WMI_UPDATE_STATS_EVENTID back-to-back
4401 * when stats data buffer limit is reached. fw_stats_complete4394 * when stats data buffer limit is reached. fw_stats_complete
4402 * is completed once host receives first event from firmware, but4395 * is completed once host receives first event from firmware, but
4403 * still end might not be marked in the TLV.4396 * still there could be more events following. Below is to wait
4404 * Below loop is to confirm that firmware completed sending all the event4397 * until firmware completes sending all the events.
4405 * and fw_stats_done is marked true when end is marked in the TLV.
4406 */4398 */
4407 for (;;) {4399 time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
4408 if (time_after(jiffies, timeout))4400 if (!time_left) {
4409 break;4401 ath12k_warn(ab, "time out while waiting for fw stats done\n");
4410 spin_lock_bh(&ar->data_lock);4402 return -ETIMEDOUT;
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);
4416 }4403 }
4404
4417 return 0;4405 return 0;
4418}4406}
4419 4407
@@ -5890,6 +5878,327 @@ exit: · 1470 unmodified lines
5890 return ret;5878 return ret;
5891}5879}
5892 5880
5881static 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
5890static bool
5891ath12k_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
5906static 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
5913static 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
5926static 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
5933static 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
5959static 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
5966static 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
6032static 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
6086static 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
6098static 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
6106static 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
5893static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,6202static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
5894 struct ieee80211_vif *vif,6203 struct ieee80211_vif *vif,
5895 struct ieee80211_sta *sta,6204 struct ieee80211_sta *sta,
@@ -5899,10 +6208,13 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, · 3 unmodified lines
5899 struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);6208 struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
5900 struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);6209 struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
5901 struct ath12k_hw *ah = ath12k_hw_to_ah(hw);6210 struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
6211 struct ath12k_base *prev_ab = NULL, *ab;
5902 struct ath12k_link_vif *arvif;6212 struct ath12k_link_vif *arvif;
5903 struct ath12k_link_sta *arsta;6213 struct ath12k_link_sta *arsta;
5904 unsigned long valid_links;6214 unsigned long valid_links;
5905 u8 link_id = 0;6215 u16 selected_links = 0;
6216 u8 link_id = 0, i;
6217 struct ath12k *ar;
5906 int ret;6218 int ret;
5907 6219
5908 lockdep_assert_wiphy(hw->wiphy);6220 lockdep_assert_wiphy(hw->wiphy);
@@ -5972,8 +6284,24 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, · 63 unmodified lines
5972 * about to move to the associated state.6284 * about to move to the associated state.
5973 */6285 */
5974 if (ieee80211_vif_is_mld(vif) && vif->type == NL80211_IFTYPE_STATION &&6286 if (ieee80211_vif_is_mld(vif) && vif->type == NL80211_IFTYPE_STATION &&
5975 old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC)6287 old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) {
5976 ieee80211_set_active_links(vif, ieee80211_vif_usable_links(vif));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 }
5977 6305
5978 /* Handle all the other state transitions in generic way */6306 /* Handle all the other state transitions in generic way */
5979 valid_links = ahsta->links_map;6307 valid_links = ahsta->links_map;
@@ -5997,6 +6325,24 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, · 17 unmodified lines
5997 }6325 }
5998 }6326 }
5999 6327
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 }
6000 /* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST:6346 /* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST:
6001 * Remove the station from driver (handle ML sta here since that6347 * Remove the station from driver (handle ML sta here since that
6002 * needs special handling. Normal sta will be handled in generic6348 * 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
54#define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS54#define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS
55#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1)55#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1)
56 56
57#define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2
58
57enum ath12k_supported_bw {59enum ath12k_supported_bw {
58 ATH12K_BW_20 = 0,60 ATH12K_BW_20 = 0,
59 ATH12K_BW_40 = 1,61 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
91 bool dma_ring_cap_done;91 bool dma_ring_cap_done;
92 bool spectral_bin_scaling_done;92 bool spectral_bin_scaling_done;
93 bool mac_phy_caps_ext_done;93 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;
94};99};
95 100
96struct ath12k_wmi_rdy_parse {101struct ath12k_wmi_rdy_parse {
@@ -4395,6 +4400,7 @@ static int ath12k_wmi_hw_mode_caps_parse(struct ath12k_base *soc, · 4298 unmodified lines
4395static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,4400static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
4396 u16 len, const void *ptr, void *data)4401 u16 len, const void *ptr, void *data)
4397{4402{
4403 struct ath12k_svc_ext_info *svc_ext_info = &soc->wmi_ab.svc_ext_info;
4398 struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;4404 struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;
4399 const struct ath12k_wmi_hw_mode_cap_params *hw_mode_caps;4405 const struct ath12k_wmi_hw_mode_cap_params *hw_mode_caps;
4400 enum wmi_host_hw_mode_config_type mode, pref;4406 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
4427 }4433 }
4428 }4434 }
4429 4435
4430 ath12k_dbg(soc, ATH12K_DBG_WMI, "preferred_hw_mode:%d\n",4436 svc_ext_info->num_hw_modes = svc_rdy_ext->n_hw_mode_caps;
4431 soc->wmi_ab.preferred_hw_mode);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
4432 if (soc->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_MAX)4441 if (soc->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
4433 return -EINVAL;4442 return -EINVAL;
4434 4443
@@ -4658,6 +4667,65 @@ free_dir_buff: · 223 unmodified lines
4658 return ret;4667 return ret;
4659}4668}
4660 4669
4670static void
4671ath12k_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
4687static void
4688ath12k_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
4661static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab,4729static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab,
4662 u16 tag, u16 len,4730 u16 tag, u16 len,
4663 const void *ptr, void *data)4731 const void *ptr, void *data)
@@ -4706,6 +4774,8 @@ static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab, · 42 unmodified lines
4706 return ret;4774 return ret;
4707 }4775 }
4708 4776
4777 ath12k_wmi_save_all_mac_phy_info(ab, svc_rdy_ext);
4778
4709 svc_rdy_ext->mac_phy_done = true;4779 svc_rdy_ext->mac_phy_done = true;
4710 } else if (!svc_rdy_ext->ext_hal_reg_done) {4780 } else if (!svc_rdy_ext->ext_hal_reg_done) {
4711 ret = ath12k_wmi_ext_hal_reg_caps(ab, len, ptr, svc_rdy_ext);4781 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
4922 return 0;4992 return 0;
4923}4993}
4924 4994
4995static void
4996ath12k_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
5029static bool
5030ath12k_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
5047static 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
5064static u32
5065ath12k_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
5078static u32
5079ath12k_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
5093static void
5094ath12k_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
5124static void
5125ath12k_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
5155static 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
5171static void
5172ath12k_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
5190static 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
5201static 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
5263static 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
5302static void
5303ath12k_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
5362static 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
5373static 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
4925static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,5433static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,
4926 u16 tag, u16 len,5434 u16 tag, u16 len,
4927 const void *ptr, void *data)5435 const void *ptr, void *data)
4928{5436{
5437 const struct ath12k_wmi_dbs_or_sbs_cap_params *dbs_or_sbs_caps;
4929 struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0];5438 struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0];
4930 struct ath12k_wmi_svc_rdy_ext2_parse *parse = data;5439 struct ath12k_wmi_svc_rdy_ext2_parse *parse = data;
4931 int ret;5440 int ret;
@@ -4967,7 +5476,32 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, · 35 unmodified lines
4967 }5476 }
4968 5477
4969 parse->mac_phy_caps_ext_done = true;5478 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;
4970 }5503 }
5504
4971 break;5505 break;
4972 default:5506 default:
4973 break;5507 break;
@@ -7626,6 +8160,64 @@ static int ath12k_wmi_pull_fw_stats(struct ath12k_base *ab, struct sk_buff *skb, · 2652 unmodified lines
7626 &parse);8160 &parse);
7627}8161}
7628 8162
8163static 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
7629static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb)8221static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb)
7630{8222{
7631 struct ath12k_fw_stats stats = {};8223 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
7655 8247
7656 spin_lock_bh(&ar->data_lock);8248 spin_lock_bh(&ar->data_lock);
7657 8249
7658 /* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via8250 /* Handle WMI_REQUEST_PDEV_STAT status update */
7659 * debugfs fw stats. Therefore, processing it separately.
7660 */
7661 if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {8251 if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
7662 list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs);8252 list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs);
7663 ar->fw_stats.fw_stats_done = true;8253 complete(&ar->fw_stats_done);
7664 goto complete;8254 goto complete;
7665 }8255 }
7666 8256
7667 /* WMI_REQUEST_VDEV_STAT and WMI_REQUEST_BCN_STAT are currently requested only8257 /* Handle WMI_REQUEST_VDEV_STAT and WMI_REQUEST_BCN_STAT updates. */
7668 * via debugfs fw stats. Hence, processing these in debugfs context.8258 ath12k_wmi_fw_stats_process(ar, &stats);
7669 */
7670 ath12k_debugfs_fw_stats_process(ar, &stats);
7671 8259
7672complete:8260complete:
7673 complete(&ar->fw_stats_complete);8261 complete(&ar->fw_stats_complete);
@@ -9911,3 +10499,224 @@ int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar, · 2237 unmodified lines
9911 10499
9912 return 0;10500 return 0;
9913}10501}
10502
10503static int
10504ath12k_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
10545int 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
10719free_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
1974 WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT,1974 WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT,
1975 WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5,1975 WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5,
1976 WMI_TAG_VDEV_CH_POWER_INFO,1976 WMI_TAG_VDEV_CH_POWER_INFO,
1977 WMI_TAG_MLO_LINK_SET_ACTIVE_CMD = 0x3BE,
1977 WMI_TAG_EHT_RATE_SET = 0x3C4,1978 WMI_TAG_EHT_RATE_SET = 0x3C4,
1978 WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5,1979 WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5,
1979 WMI_TAG_MLO_TX_SEND_PARAMS,1980 WMI_TAG_MLO_TX_SEND_PARAMS,
@@ -2617,6 +2618,8 @@ struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params { · 637 unmodified lines
2617 __le32 num_chainmask_tables;2618 __le32 num_chainmask_tables;
2618} __packed;2619} __packed;
2619 2620
2621#define WMI_HW_MODE_CAP_CFG_TYPE GENMASK(27, 0)
2622
2620struct ath12k_wmi_hw_mode_cap_params {2623struct ath12k_wmi_hw_mode_cap_params {
2621 __le32 tlv_header;2624 __le32 tlv_header;
2622 __le32 hw_mode_id;2625 __le32 hw_mode_id;
@@ -2666,6 +2669,12 @@ struct ath12k_wmi_mac_phy_caps_params { · 43 unmodified lines
2666 __le32 he_cap_info_2g_ext;2669 __le32 he_cap_info_2g_ext;
2667 __le32 he_cap_info_5g_ext;2670 __le32 he_cap_info_5g_ext;
2668 __le32 he_cap_info_internal;2671 __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;
2669} __packed;2678} __packed;
2670 2679
2671struct ath12k_wmi_hal_reg_caps_ext_params {2680struct ath12k_wmi_hal_reg_caps_ext_params {
@@ -2739,6 +2748,11 @@ struct wmi_service_ready_ext2_event { · 67 unmodified lines
2739 __le32 default_num_msduq_supported_per_tid;2748 __le32 default_num_msduq_supported_per_tid;
2740} __packed;2749} __packed;
2741 2750
2751struct ath12k_wmi_dbs_or_sbs_cap_params {
2752 __le32 hw_mode_id;
2753 __le32 sbs_lower_band_end_freq;
2754} __packed;
2755
2742struct ath12k_wmi_caps_ext_params {2756struct ath12k_wmi_caps_ext_params {
2743 __le32 hw_mode_id;2757 __le32 hw_mode_id;
2744 __le32 pdev_and_hw_link_ids;2758 __le32 pdev_and_hw_link_ids;
@@ -5049,6 +5063,53 @@ struct ath12k_wmi_pdev { · 2304 unmodified lines
5049 u32 rx_decap_mode;5063 u32 rx_decap_mode;
5050};5064};
5051 5065
5066struct 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
5073struct 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
5082struct 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 */
5096enum 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
5105struct 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
5052struct ath12k_wmi_base {5113struct ath12k_wmi_base {
5053 struct ath12k_base *ab;5114 struct ath12k_base *ab;
5054 struct ath12k_wmi_pdev wmi[MAX_RADIOS];5115 struct ath12k_wmi_pdev wmi[MAX_RADIOS];
@@ -5066,6 +5127,10 @@ struct ath12k_wmi_base { · 11 unmodified lines
5066 enum wmi_host_hw_mode_config_type preferred_hw_mode;5127 enum wmi_host_hw_mode_config_type preferred_hw_mode;
5067 5128
5068 struct ath12k_wmi_target_cap_arg *targ_cap;5129 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;
5069};5134};
5070 5135
5071struct wmi_pdev_set_bios_interface_cmd {5136struct wmi_pdev_set_bios_interface_cmd {
@@ -5997,6 +6062,118 @@ struct wmi_vdev_set_tpc_power_cmd { · 925 unmodified lines
5997 */6062 */
5998} __packed;6063} __packed;
5999 6064
6065#define CRTL_F_DYNC_FORCE_LINK_NUM GENMASK(3, 2)
6066
6067struct 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
6076struct 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
6089struct wmi_disallowed_mlo_mode_bitmap_params {
6090 __le32 tlv_header;
6091 __le32 disallowed_mode_bitmap;
6092 __le32 ieee_link_id_comb;
6093} __packed;
6094
6095enum 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
6105enum 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
6115struct wmi_mlo_link_num_arg {
6116 u32 num_of_link;
6117 u32 vdev_type;
6118 u32 vdev_subtype;
6119 u32 home_freq;
6120};
6121
6122struct 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
6131struct 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
6138struct 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
6161struct 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
6000void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,6177void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
6001 struct ath12k_wmi_resource_config_arg *config);6178 struct ath12k_wmi_resource_config_arg *config);
6002void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,6179void 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
6195int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar,6372int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar,
6196 u32 vdev_id,6373 u32 vdev_id,
6197 struct ath12k_reg_tpc_power_info *param);6374 struct ath12k_reg_tpc_power_info *param);
6198 6375int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
6376 struct wmi_mlo_link_set_active_arg *param);
6199#endif6377#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
87 * We need to do some backwards compatibility to make this work.87 * We need to do some backwards compatibility to make this work.
88 */88 */
89 if (le32_to_cpu(targ_info->byte_count) != sizeof(*targ_info)) {89 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));
91 return -EINVAL;93 return -EINVAL;
92 }94 }
93 95
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
438 438
439 if (atomic_read(&ar->rx_anch_urbs) == 0) {439 if (atomic_read(&ar->rx_anch_urbs) == 0) {
440 /*440 /*
441 * The system is too slow to cope with441 * At this point, either the system is too slow to
442 * the enormous workload. We have simply442 * cope with the enormous workload (so we have simply
443 * run out of active rx urbs and this443 * run out of active rx urbs and this unfortunately
444 * unfortunately leads to an unpredictable444 * leads to an unpredictable device), or the device
445 * 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).
446 */449 */
447 450
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));
449 }456 }
450 } else {457 } else {
451 /*458 /*
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
1316 sizeof(trans->conf.no_reclaim_cmds));1316 sizeof(trans->conf.no_reclaim_cmds));
1317 memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,1317 memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,
1318 sizeof(no_reclaim_cmds));1318 sizeof(no_reclaim_cmds));
1319 trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
1319 1320
1320 switch (iwlwifi_mod_params.amsdu_size) {1321 switch (iwlwifi_mod_params.amsdu_size) {
1321 case IWL_AMSDU_DEF:1322 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
77 77
78 /* Setup async RX handling */78 /* Setup async RX handling */
79 spin_lock_init(&mld->async_handlers_lock);79 spin_lock_init(&mld->async_handlers_lock);
80 INIT_LIST_HEAD(&mld->async_handlers_list);
80 wiphy_work_init(&mld->async_handlers_wk,81 wiphy_work_init(&mld->async_handlers_wk,
81 iwl_mld_async_handlers_wk);82 iwl_mld_async_handlers_wk);
82 83
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
34 WIDE_ID(MAC_CONF_GROUP,34 WIDE_ID(MAC_CONF_GROUP,
35 MAC_CONFIG_CMD), 0);35 MAC_CONFIG_CMD), 0);
36 36
37 if (WARN_ON(cmd_ver < 1 && cmd_ver > 3))37 if (WARN_ON(cmd_ver < 1 || cmd_ver > 3))
38 return;38 return;
39 39
40 cmd->id_and_color = cpu_to_le32(mvmvif->id);40 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
166 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);166 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
167 struct iwl_context_info *ctxt_info;167 struct iwl_context_info *ctxt_info;
168 struct iwl_context_info_rbd_cfg *rx_cfg;168 struct iwl_context_info_rbd_cfg *rx_cfg;
169 u32 control_flags = 0, rb_size;169 u32 control_flags = 0, rb_size, cb_size;
170 dma_addr_t phys;170 dma_addr_t phys;
171 int ret;171 int ret;
172 172
@@ -202,11 +202,12 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, · 29 unmodified lines
202 rb_size = IWL_CTXT_INFO_RB_SIZE_4K;202 rb_size = IWL_CTXT_INFO_RB_SIZE_4K;
203 }203 }
204 204
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
206 control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG;209 control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG;
207 control_flags |=210 control_flags |= u32_encode_bits(cb_size, IWL_CTXT_INFO_RB_CB_SIZE);
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(rb_size, IWL_CTXT_INFO_RB_SIZE);211 control_flags |= u32_encode_bits(rb_size, IWL_CTXT_INFO_RB_SIZE);
211 ctxt_info->control.control_flags = cpu_to_le32(control_flags);212 ctxt_info->control.control_flags = cpu_to_le32(control_flags);
212 213
include/linux/ieee80211.h+9−9
@@ -1278,7 +1278,7 @@ struct ieee80211_ext { · 1277 unmodified lines
1278 u8 sa[ETH_ALEN];1278 u8 sa[ETH_ALEN];
1279 __le32 timestamp;1279 __le32 timestamp;
1280 u8 change_seq;1280 u8 change_seq;
1281 u8 variable[0];1281 u8 variable[];
1282 } __packed s1g_beacon;1282 } __packed s1g_beacon;
1283 } u;1283 } u;
1284} __packed __aligned(2);1284} __packed __aligned(2);
@@ -1536,7 +1536,7 @@ struct ieee80211_mgmt { · 251 unmodified lines
1536 u8 action_code;1536 u8 action_code;
1537 u8 dialog_token;1537 u8 dialog_token;
1538 __le16 capability;1538 __le16 capability;
1539 u8 variable[0];1539 u8 variable[];
1540 } __packed tdls_discover_resp;1540 } __packed tdls_discover_resp;
1541 struct {1541 struct {
1542 u8 action_code;1542 u8 action_code;
@@ -1721,35 +1721,35 @@ struct ieee80211_tdls_data { · 178 unmodified lines
1721 struct {1721 struct {
1722 u8 dialog_token;1722 u8 dialog_token;
1723 __le16 capability;1723 __le16 capability;
1724 u8 variable[0];1724 u8 variable[];
1725 } __packed setup_req;1725 } __packed setup_req;
1726 struct {1726 struct {
1727 __le16 status_code;1727 __le16 status_code;
1728 u8 dialog_token;1728 u8 dialog_token;
1729 __le16 capability;1729 __le16 capability;
1730 u8 variable[0];1730 u8 variable[];
1731 } __packed setup_resp;1731 } __packed setup_resp;
1732 struct {1732 struct {
1733 __le16 status_code;1733 __le16 status_code;
1734 u8 dialog_token;1734 u8 dialog_token;
1735 u8 variable[0];1735 u8 variable[];
1736 } __packed setup_cfm;1736 } __packed setup_cfm;
1737 struct {1737 struct {
1738 __le16 reason_code;1738 __le16 reason_code;
1739 u8 variable[0];1739 u8 variable[];
1740 } __packed teardown;1740 } __packed teardown;
1741 struct {1741 struct {
1742 u8 dialog_token;1742 u8 dialog_token;
1743 u8 variable[0];1743 u8 variable[];
1744 } __packed discover_req;1744 } __packed discover_req;
1745 struct {1745 struct {
1746 u8 target_channel;1746 u8 target_channel;
1747 u8 oper_class;1747 u8 oper_class;
1748 u8 variable[0];1748 u8 variable[];
1749 } __packed chan_switch_req;1749 } __packed chan_switch_req;
1750 struct {1750 struct {
1751 __le16 status_code;1751 __le16 status_code;
1752 u8 variable[0];1752 u8 variable[];
1753 } __packed chan_switch_resp;1753 } __packed chan_switch_resp;
1754 } u;1754 } u;
1755} __packed;1755} __packed;
net/mac80211/debug.h+4−1
@@ -1,10 +1,11 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2/*2/*
3 * Portions3 * Portions
4 * Copyright (C) 2022 - 2024 Intel Corporation4 * Copyright (C) 2022 - 2025 Intel Corporation
5 */5 */
6#ifndef __MAC80211_DEBUG_H6#ifndef __MAC80211_DEBUG_H
7#define __MAC80211_DEBUG_H7#define __MAC80211_DEBUG_H
8#include <linux/once_lite.h>
8#include <net/cfg80211.h>9#include <net/cfg80211.h>
9 10
10#ifdef CONFIG_MAC80211_OCB_DEBUG11#ifdef CONFIG_MAC80211_OCB_DEBUG
@@ -152,6 +153,8 @@ do { \ · 141 unmodified lines
152 else \153 else \
153 _sdata_err((link)->sdata, fmt, ##__VA_ARGS__); \154 _sdata_err((link)->sdata, fmt, ##__VA_ARGS__); \
154 } while (0)155 } while (0)
156#define link_err_once(link, fmt, ...) \
157 DO_ONCE_LITE(link_err, link, fmt, ##__VA_ARGS__)
155#define link_id_info(sdata, link_id, fmt, ...) \158#define link_id_info(sdata, link_id, fmt, ...) \
156 do { \159 do { \
157 if (ieee80211_vif_is_mld(&sdata->vif)) \160 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
4432 if (!multicast &&4432 if (!multicast &&
4433 !ether_addr_equal(sdata->dev->dev_addr, hdr->addr1))4433 !ether_addr_equal(sdata->dev->dev_addr, hdr->addr1))
4434 return false;4434 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;
4435 if (!rx->sta) {4439 if (!rx->sta) {
4436 int rate_idx;4440 int rate_idx;
4437 if (status->encoding != RX_ENC_LEGACY)4441 if (status->encoding != RX_ENC_LEGACY)
net/mac80211/tx.c+21−8
@@ -5,7 +5,7 @@ · 4 unmodified lines
5 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>5 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
6 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>6 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
7 * Copyright 2013-2014 Intel Mobile Communications GmbH7 * Copyright 2013-2014 Intel Mobile Communications GmbH
8 * Copyright (C) 2018-2024 Intel Corporation8 * Copyright (C) 2018-2025 Intel Corporation
9 *9 *
10 * Transmit and frame generation functions.10 * Transmit and frame generation functions.
11 */11 */
@@ -5016,12 +5016,25 @@ static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata, · 5004 unmodified lines
5016 }5016 }
5017}5017}
5018 5018
5019static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon)5019static u8 __ieee80211_beacon_update_cntdwn(struct ieee80211_link_data *link,
5020 struct beacon_data *beacon)
5020{5021{
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 }
5022 5036
5023 /* the counter should never reach 0 */5037 beacon->cntdwn_current_counter--;
5024 WARN_ON_ONCE(!beacon->cntdwn_current_counter);
5025 5038
5026 return beacon->cntdwn_current_counter;5039 return beacon->cntdwn_current_counter;
5027}5040}
@@ -5052,7 +5065,7 @@ u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif, unsigned int link_i · 24 unmodified lines
5052 if (!beacon)5065 if (!beacon)
5053 goto unlock;5066 goto unlock;
5054 5067
5055 count = __ieee80211_beacon_update_cntdwn(beacon);5068 count = __ieee80211_beacon_update_cntdwn(link, beacon);
5056 5069
5057unlock:5070unlock:
5058 rcu_read_unlock();5071 rcu_read_unlock();
@@ -5450,7 +5463,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, · 391 unmodified lines
5450 5463
5451 if (beacon->cntdwn_counter_offsets[0]) {5464 if (beacon->cntdwn_counter_offsets[0]) {
5452 if (!is_template)5465 if (!is_template)
5453 __ieee80211_beacon_update_cntdwn(beacon);5466 __ieee80211_beacon_update_cntdwn(link, beacon);
5454 5467
5455 ieee80211_set_beacon_cntdwn(sdata, beacon, link);5468 ieee80211_set_beacon_cntdwn(sdata, beacon, link);
5456 }5469 }
@@ -5482,7 +5495,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, · 25 unmodified lines
5482 * for now we leave it consistent with overall5495 * for now we leave it consistent with overall
5483 * mac80211's behavior.5496 * mac80211's behavior.
5484 */5497 */
5485 __ieee80211_beacon_update_cntdwn(beacon);5498 __ieee80211_beacon_update_cntdwn(link, beacon);
5486 5499
5487 ieee80211_set_beacon_cntdwn(sdata, beacon, link);5500 ieee80211_set_beacon_cntdwn(sdata, beacon, link);
5488 }5501 }