diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath12k/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath12k/mac.c | 1850 |
1 files changed, 1164 insertions, 686 deletions
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 137394c36460..d493ec812055 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -250,10 +250,10 @@ static const u32 ath12k_smps_map[] = { }; static int ath12k_start_vdev_delay(struct ath12k *ar, - struct ath12k_vif *arvif); + struct ath12k_link_vif *arvif); static void ath12k_mac_stop(struct ath12k *ar); -static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif); -static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif); +static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif); +static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arvif); static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode) { @@ -476,18 +476,25 @@ static u8 ath12k_parse_mpdudensity(u8 mpdudensity) } } -static int ath12k_mac_vif_chan(struct ieee80211_vif *vif, - struct cfg80211_chan_def *def) +static int ath12k_mac_vif_link_chan(struct ieee80211_vif *vif, u8 link_id, + struct cfg80211_chan_def *def) { + struct ieee80211_bss_conf *link_conf; struct ieee80211_chanctx_conf *conf; rcu_read_lock(); - conf = rcu_dereference(vif->bss_conf.chanctx_conf); + link_conf = rcu_dereference(vif->link_conf[link_id]); + + if (!link_conf) { + rcu_read_unlock(); + return -ENOLINK; + } + + conf = rcu_dereference(link_conf->chanctx_conf); if (!conf) { rcu_read_unlock(); return -ENOENT; } - *def = conf->def; rcu_read_unlock(); @@ -539,18 +546,33 @@ static void ath12k_get_arvif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct ath12k_vif_iter *arvif_iter = data; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + unsigned long links_map = ahvif->links_map; + struct ath12k_link_vif *arvif; + u8 link_id; + + for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = rcu_dereference(ahvif->link[link_id]); + + if (WARN_ON(!arvif)) + continue; - if (arvif->vdev_id == arvif_iter->vdev_id && - arvif->ar == arvif_iter->ar) - arvif_iter->arvif = arvif; + if (arvif->vdev_id == arvif_iter->vdev_id && + arvif->ar == arvif_iter->ar) { + arvif_iter->arvif = arvif; + break; + } + } } -struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id) +struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id) { struct ath12k_vif_iter arvif_iter = {}; u32 flags; + /* To use the arvif returned, caller must have held rcu read lock. + */ + WARN_ON(!rcu_read_lock_any_held()); arvif_iter.vdev_id = vdev_id; arvif_iter.ar = ar; @@ -567,12 +589,12 @@ struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id) return arvif_iter.arvif; } -struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab, - u32 vdev_id) +struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab, + u32 vdev_id) { int i; struct ath12k_pdev *pdev; - struct ath12k_vif *arvif; + struct ath12k_link_vif *arvif; for (i = 0; i < ab->num_radios; i++) { pdev = rcu_dereference(ab->pdevs_active[i]); @@ -658,7 +680,8 @@ static struct ath12k *ath12k_get_ar_by_ctx(struct ieee80211_hw *hw, static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif = &ahvif->deflink; struct ath12k_hw *ah = ath12k_hw_to_ah(hw); /* If there is one pdev within ah, then we return @@ -673,11 +696,12 @@ static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, return NULL; } -static struct ath12k_vif *ath12k_mac_get_vif_up(struct ath12k *ar) +static struct ath12k_link_vif *ath12k_mac_get_vif_up(struct ath12k *ar) { - struct ath12k_vif *arvif; + struct ath12k_link_vif *arvif; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - lockdep_assert_held(&ar->conf_mutex); list_for_each_entry(arvif, &ar->arvifs, list) { if (arvif->is_up) return arvif; @@ -705,17 +729,17 @@ static bool ath12k_mac_band_match(enum nl80211_band band1, enum WMI_HOST_WLAN_BA return false; } -static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_vif *arvif) +static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_link_vif *arvif) { struct ath12k *ar = arvif->ar; struct ath12k_base *ab = ar->ab; - struct ieee80211_vif *vif = arvif->vif; + struct ieee80211_vif *vif = arvif->ahvif->vif; struct cfg80211_chan_def def; enum nl80211_band band; u8 pdev_id = ab->fw_pdev[0].pdev_id; int i; - if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return pdev_id; band = def.chan->band; @@ -730,7 +754,7 @@ static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_vif *arvif) u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar) { - struct ath12k_vif *arvif; + struct ath12k_link_vif *arvif; struct ath12k_base *ab = ar->ab; if (!ab->hw_params->single_pdev_only) @@ -770,11 +794,11 @@ static void ath12k_pdev_caps_update(struct ath12k *ar) static int ath12k_mac_txpower_recalc(struct ath12k *ar) { struct ath12k_pdev *pdev = ar->pdev; - struct ath12k_vif *arvif; + struct ath12k_link_vif *arvif; int ret, txpower = -1; u32 param; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); list_for_each_entry(arvif, &ar->arvifs, list) { if (arvif->txpower <= 0) @@ -824,13 +848,13 @@ fail: return ret; } -static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif) +static int ath12k_recalc_rtscts_prot(struct ath12k_link_vif *arvif) { struct ath12k *ar = arvif->ar; u32 vdev_param, rts_cts; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); vdev_param = WMI_VDEV_PARAM_ENABLE_RTSCTS; @@ -863,7 +887,7 @@ static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif) return ret; } -static int ath12k_mac_set_kickout(struct ath12k_vif *arvif) +static int ath12k_mac_set_kickout(struct ath12k_link_vif *arvif) { struct ath12k *ar = arvif->ar; u32 param; @@ -913,11 +937,14 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) struct ath12k_peer *peer, *tmp; struct ath12k_base *ab = ar->ab; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); spin_lock_bh(&ab->base_lock); list_for_each_entry_safe(peer, tmp, &ab->peers, list) { - ath12k_dp_rx_peer_tid_cleanup(ar, peer); + /* Skip Rx TID cleanup for self peer */ + if (peer->sta) + ath12k_dp_rx_peer_tid_cleanup(ar, peer); + list_del(&peer->list); kfree(peer); } @@ -929,7 +956,7 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) static int ath12k_mac_vdev_setup_sync(struct ath12k *ar) { - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) return -ESHUTDOWN; @@ -971,7 +998,7 @@ static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id, struct ath12k_wmi_vdev_up_params params = {}; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); channel = chandef->chan; arg.vdev_id = vdev_id; @@ -1034,7 +1061,7 @@ static int ath12k_mac_monitor_vdev_stop(struct ath12k *ar) { int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); reinit_completion(&ar->vdev_setup_done); @@ -1064,9 +1091,8 @@ static int ath12k_mac_monitor_vdev_create(struct ath12k *ar) struct ath12k_wmi_vdev_create_arg arg = {}; int bit, ret; u8 tmp_addr[6]; - u16 nss; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (ar->monitor_vdev_created) return 0; @@ -1104,19 +1130,6 @@ static int ath12k_mac_monitor_vdev_create(struct ath12k *ar) return ret; } - nss = hweight32(ar->cfg_tx_chainmask) ? : 1; - ret = ath12k_wmi_vdev_set_param_cmd(ar, ar->monitor_vdev_id, - WMI_VDEV_PARAM_NSS, nss); - if (ret) { - ath12k_warn(ar->ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n", - ar->monitor_vdev_id, ar->cfg_tx_chainmask, nss, ret); - return ret; - } - - ret = ath12k_mac_txpower_recalc(ar); - if (ret) - return ret; - ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id; ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id); ar->num_created_vdevs++; @@ -1132,7 +1145,7 @@ static int ath12k_mac_monitor_vdev_delete(struct ath12k *ar) int ret; unsigned long time_left; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (!ar->monitor_vdev_created) return 0; @@ -1178,7 +1191,7 @@ static int ath12k_mac_monitor_start(struct ath12k *ar) struct cfg80211_chan_def *chandef = NULL; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (ar->monitor_started) return 0; @@ -1208,7 +1221,7 @@ static int ath12k_mac_monitor_stop(struct ath12k *ar) { int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (!ar->monitor_started) return 0; @@ -1226,12 +1239,13 @@ static int ath12k_mac_monitor_stop(struct ath12k *ar) return ret; } -static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif) +static int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif) { + struct ath12k_vif *ahvif = arvif->ahvif; struct ath12k *ar = arvif->ar; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); reinit_completion(&ar->vdev_setup_done); @@ -1253,7 +1267,7 @@ static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif) ar->num_started_vdevs--; ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n", - arvif->vif->addr, arvif->vdev_id); + ahvif->vif->addr, arvif->vdev_id); if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) { clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); @@ -1272,36 +1286,33 @@ static int ath12k_mac_config(struct ath12k *ar, u32 changed) struct ieee80211_conf *conf = &hw->conf; int ret = 0; - mutex_lock(&ar->conf_mutex); + lockdep_assert_wiphy(hw->wiphy); if (changed & IEEE80211_CONF_CHANGE_MONITOR) { ar->monitor_conf_enabled = conf->flags & IEEE80211_CONF_MONITOR; if (ar->monitor_conf_enabled) { if (ar->monitor_vdev_created) - goto exit; + return ret; ret = ath12k_mac_monitor_vdev_create(ar); if (ret) - goto exit; + return ret; ret = ath12k_mac_monitor_start(ar); if (ret) goto err_mon_del; } else { if (!ar->monitor_vdev_created) - goto exit; + return ret; ret = ath12k_mac_monitor_stop(ar); if (ret) - goto exit; + return ret; ath12k_mac_monitor_vdev_delete(ar); } } -exit: - mutex_unlock(&ar->conf_mutex); return ret; err_mon_del: ath12k_mac_monitor_vdev_delete(ar); - mutex_unlock(&ar->conf_mutex); return ret; } @@ -1311,6 +1322,8 @@ static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed) struct ath12k *ar; int ret; + lockdep_assert_wiphy(hw->wiphy); + ar = ath12k_ah_to_ar(ah, 0); ret = ath12k_mac_config(ar, changed); @@ -1321,7 +1334,7 @@ static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed) return ret; } -static int ath12k_mac_setup_bcn_p2p_ie(struct ath12k_vif *arvif, +static int ath12k_mac_setup_bcn_p2p_ie(struct ath12k_link_vif *arvif, struct sk_buff *bcn) { struct ath12k *ar = arvif->ar; @@ -1378,7 +1391,7 @@ static int ath12k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui, return 0; } -static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *bcn, +static void ath12k_mac_set_arvif_ies(struct ath12k_link_vif *arvif, struct sk_buff *bcn, u8 bssid_index, bool *nontx_profile_found) { struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)bcn->data; @@ -1470,19 +1483,22 @@ static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *b } } -static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_vif *arvif) +static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_link_vif *arvif) { - struct ieee80211_bss_conf *bss_conf = &arvif->vif->bss_conf; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_bss_conf *bss_conf = &ahvif->vif->bss_conf; struct ath12k_wmi_bcn_tmpl_ema_arg ema_args; struct ieee80211_ema_beacons *beacons; - struct ath12k_vif *tx_arvif; + struct ath12k_link_vif *tx_arvif; bool nontx_profile_found = false; + struct ath12k_vif *tx_ahvif; int ret = 0; u8 i; - tx_arvif = ath12k_vif_to_arvif(arvif->vif->mbssid_tx_vif); + tx_ahvif = ath12k_vif_to_ahvif(ahvif->vif->mbssid_tx_vif); + tx_arvif = &tx_ahvif->deflink; beacons = ieee80211_beacon_get_template_ema_list(ath12k_ar_to_hw(tx_arvif->ar), - tx_arvif->vif, 0); + tx_ahvif->vif, 0); if (!beacons || !beacons->cnt) { ath12k_warn(arvif->ar->ab, "failed to get ema beacon templates from mac80211\n"); @@ -1520,22 +1536,25 @@ static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_vif *arvif) return ret; } -static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif) +static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif) { - struct ath12k_vif *tx_arvif = arvif; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); + struct ath12k_link_vif *tx_arvif = arvif; struct ath12k *ar = arvif->ar; struct ath12k_base *ab = ar->ab; - struct ieee80211_vif *vif = arvif->vif; struct ieee80211_mutable_offsets offs = {}; + struct ath12k_vif *tx_ahvif = ahvif; bool nontx_profile_found = false; struct sk_buff *bcn; int ret; - if (arvif->vdev_type != WMI_VDEV_TYPE_AP) + if (ahvif->vdev_type != WMI_VDEV_TYPE_AP) return 0; if (vif->mbssid_tx_vif) { - tx_arvif = ath12k_vif_to_arvif(vif->mbssid_tx_vif); + tx_ahvif = ath12k_vif_to_ahvif(vif->mbssid_tx_vif); + tx_arvif = &tx_ahvif->deflink; if (tx_arvif != arvif && arvif->is_up) return 0; @@ -1543,7 +1562,7 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif) return ath12k_mac_setup_bcn_tmpl_ema(arvif); } - bcn = ieee80211_beacon_get_template(ath12k_ar_to_hw(tx_arvif->ar), tx_arvif->vif, + bcn = ieee80211_beacon_get_template(ath12k_ar_to_hw(tx_arvif->ar), tx_ahvif->vif, &offs, 0); if (!bcn) { ath12k_warn(ab, "failed to get beacon template from mac80211\n"); @@ -1554,14 +1573,14 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif) ath12k_mac_set_arvif_ies(arvif, bcn, 0, NULL); } else { ath12k_mac_set_arvif_ies(arvif, bcn, - arvif->vif->bss_conf.bssid_index, + ahvif->vif->bss_conf.bssid_index, &nontx_profile_found); if (!nontx_profile_found) ath12k_warn(ab, "nontransmitted profile not found in beacon template\n"); } - if (arvif->vif->type == NL80211_IFTYPE_AP && arvif->vif->p2p) { + if (ahvif->vif->type == NL80211_IFTYPE_AP && ahvif->vif->p2p) { ret = ath12k_mac_setup_bcn_p2p_ie(arvif, bcn); if (ret) { ath12k_warn(ab, "failed to setup P2P GO bcn ie: %d\n", @@ -1595,14 +1614,15 @@ free_bcn_skb: return ret; } -static void ath12k_control_beaconing(struct ath12k_vif *arvif, +static void ath12k_control_beaconing(struct ath12k_link_vif *arvif, struct ieee80211_bss_conf *info) { struct ath12k_wmi_vdev_up_params params = {}; + struct ath12k_vif *ahvif = arvif->ahvif; struct ath12k *ar = arvif->ar; int ret; - lockdep_assert_held(&arvif->ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(arvif->ar)->wiphy); if (!info->enable_beacon) { ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id); @@ -1622,15 +1642,19 @@ static void ath12k_control_beaconing(struct ath12k_vif *arvif, return; } - arvif->aid = 0; + ahvif->aid = 0; ether_addr_copy(arvif->bssid, info->bssid); params.vdev_id = arvif->vdev_id; - params.aid = arvif->aid; + params.aid = ahvif->aid; params.bssid = arvif->bssid; - if (arvif->vif->mbssid_tx_vif) { - params.tx_bssid = ath12k_vif_to_arvif(arvif->vif->mbssid_tx_vif)->bssid; + if (ahvif->vif->mbssid_tx_vif) { + struct ath12k_vif *tx_ahvif = + ath12k_vif_to_ahvif(ahvif->vif->mbssid_tx_vif); + struct ath12k_link_vif *tx_arvif = &tx_ahvif->deflink; + + params.tx_bssid = tx_arvif->bssid; params.nontx_profile_idx = info->bssid_index; params.nontx_profile_cnt = 1 << info->bssid_indicator; } @@ -1651,7 +1675,8 @@ static void ath12k_mac_handle_beacon_iter(void *data, u8 *mac, { struct sk_buff *skb = data; struct ieee80211_mgmt *mgmt = (void *)skb->data; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif = &ahvif->deflink; if (vif->type != NL80211_IFTYPE_STATION) return; @@ -1674,7 +1699,8 @@ static void ath12k_mac_handle_beacon_miss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { u32 *vdev_id = data; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif = &ahvif->deflink; struct ath12k *ar = arvif->ar; struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); @@ -1705,9 +1731,9 @@ void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id) static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work) { - struct ath12k_vif *arvif = container_of(work, struct ath12k_vif, - connection_loss_work.work); - struct ieee80211_vif *vif = arvif->vif; + struct ath12k_link_vif *arvif = container_of(work, struct ath12k_link_vif, + connection_loss_work.work); + struct ieee80211_vif *vif = arvif->ahvif->vif; if (!arvif->is_up) return; @@ -1716,15 +1742,16 @@ static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work) } static void ath12k_peer_assoc_h_basic(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); u32 aid; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(hw->wiphy); if (vif->type == NL80211_IFTYPE_STATION) aid = vif->cfg.aid; @@ -1742,21 +1769,22 @@ static void ath12k_peer_assoc_h_basic(struct ath12k *ar, } static void ath12k_peer_assoc_h_crypto(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ieee80211_bss_conf *info = &vif->bss_conf; struct cfg80211_chan_def def; struct cfg80211_bss *bss; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); const u8 *rsnie = NULL; const u8 *wpaie = NULL; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(hw->wiphy); - if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return; bss = cfg80211_get_bss(hw->wiphy, def.chan, info->bssid, NULL, 0, @@ -1804,11 +1832,12 @@ static void ath12k_peer_assoc_h_crypto(struct ath12k *ar, } static void ath12k_peer_assoc_h_rates(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates; struct cfg80211_chan_def def; const struct ieee80211_supported_band *sband; @@ -1819,9 +1848,9 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar, u8 rate; int i; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(hw->wiphy); - if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return; band = def.chan->band; @@ -1867,12 +1896,13 @@ ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask) } static void ath12k_peer_assoc_h_ht(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct cfg80211_chan_def def; enum nl80211_band band; const u8 *ht_mcs_mask; @@ -1880,9 +1910,9 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar, u8 max_nss; u32 stbc; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return; if (!ht_cap->ht_supported) @@ -2028,12 +2058,13 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set, } static void ath12k_peer_assoc_h_vht(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct cfg80211_chan_def def; enum nl80211_band band; const u16 *vht_mcs_mask; @@ -2042,7 +2073,9 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, u8 max_nss, vht_mcs; int i; - if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return; if (!vht_cap->vht_supported) @@ -2123,10 +2156,12 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, } static void ath12k_peer_assoc_h_he(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; int i; u8 ampdu_factor, max_nss; @@ -2278,16 +2313,18 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar, } static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; struct cfg80211_chan_def def; enum nl80211_band band; u8 ampdu_factor, mpdu_density; - if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return; band = def.chan->band; @@ -2347,9 +2384,10 @@ static int ath12k_get_smps_from_capa(const struct ieee80211_sta_ht_cap *ht_cap, return 0; } -static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta, +static void ath12k_peer_assoc_h_smps(struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); const struct ieee80211_he_6ghz_capa *he_6ghz_capa = &sta->deflink.he_6ghz_capa; const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; int smps; @@ -2376,13 +2414,13 @@ static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta, } static void ath12k_peer_assoc_h_qos(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); - switch (arvif->vdev_type) { + switch (arvif->ahvif->vdev_type) { case WMI_VDEV_TYPE_AP: if (sta->wme) { /* TODO: Check WME vs QoS */ @@ -2412,15 +2450,16 @@ static void ath12k_peer_assoc_h_qos(struct ath12k *ar, } static int ath12k_peer_assoc_qos_ap(struct ath12k *ar, - struct ath12k_vif *arvif, - struct ieee80211_sta *sta) + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) { + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k_wmi_ap_ps_arg arg; u32 max_sp; u32 uapsd; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); arg.vdev_id = arvif->vdev_id; @@ -2574,18 +2613,22 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar, } static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct cfg80211_chan_def def; enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; enum wmi_phy_mode phymode = MODE_UNKNOWN; - if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); + + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return; band = def.chan->band; @@ -2719,17 +2762,19 @@ static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres, } static void ath12k_peer_assoc_h_eht(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20; const struct ieee80211_eht_mcs_nss_supp_bw *bw; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); u32 *rx_mcs, *tx_mcs; + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht) return; @@ -2802,34 +2847,34 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar, } static void ath12k_peer_assoc_prepare(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ath12k_wmi_peer_assoc_arg *arg, bool reassoc) { - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); memset(arg, 0, sizeof(*arg)); reinit_completion(&ar->peer_assoc_done); arg->peer_new_assoc = !reassoc; - ath12k_peer_assoc_h_basic(ar, vif, sta, arg); - ath12k_peer_assoc_h_crypto(ar, vif, sta, arg); - ath12k_peer_assoc_h_rates(ar, vif, sta, arg); - ath12k_peer_assoc_h_ht(ar, vif, sta, arg); - ath12k_peer_assoc_h_vht(ar, vif, sta, arg); - ath12k_peer_assoc_h_he(ar, vif, sta, arg); - ath12k_peer_assoc_h_he_6ghz(ar, vif, sta, arg); - ath12k_peer_assoc_h_eht(ar, vif, sta, arg); - ath12k_peer_assoc_h_qos(ar, vif, sta, arg); - ath12k_peer_assoc_h_phymode(ar, vif, sta, arg); - ath12k_peer_assoc_h_smps(sta, arg); + ath12k_peer_assoc_h_basic(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_rates(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_ht(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_vht(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_he(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_he_6ghz(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_eht(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_qos(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_phymode(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_smps(arsta, arg); /* TODO: amsdu_disable req? */ } -static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif, +static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_link_vif *arvif, const u8 *addr, const struct ieee80211_sta_ht_cap *ht_cap, const struct ieee80211_he_6ghz_capa *he_6ghz_capa) @@ -2849,21 +2894,24 @@ static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif, } static void ath12k_bss_assoc(struct ath12k *ar, - struct ath12k_vif *arvif, + struct ath12k_link_vif *arvif, struct ieee80211_bss_conf *bss_conf) { - struct ieee80211_vif *vif = arvif->vif; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); struct ath12k_wmi_vdev_up_params params = {}; struct ath12k_wmi_peer_assoc_arg peer_arg; + struct ath12k_link_sta *arsta; struct ieee80211_sta *ap_sta; + struct ath12k_sta *ahsta; struct ath12k_peer *peer; bool is_auth = false; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n", - arvif->vdev_id, arvif->bssid, arvif->aid); + arvif->vdev_id, arvif->bssid, ahvif->aid); rcu_read_lock(); @@ -2875,7 +2923,15 @@ static void ath12k_bss_assoc(struct ath12k *ar, return; } - ath12k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false); + ahsta = ath12k_sta_to_ahsta(ap_sta); + arsta = &ahsta->deflink; + + if (WARN_ON(!arsta)) { + rcu_read_unlock(); + return; + } + + ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, false); rcu_read_unlock(); @@ -2903,11 +2959,11 @@ static void ath12k_bss_assoc(struct ath12k *ar, WARN_ON(arvif->is_up); - arvif->aid = vif->cfg.aid; + ahvif->aid = vif->cfg.aid; ether_addr_copy(arvif->bssid, bss_conf->bssid); params.vdev_id = arvif->vdev_id; - params.aid = arvif->aid; + params.aid = ahvif->aid; params.bssid = arvif->bssid; ret = ath12k_wmi_vdev_up(ar, ¶ms); if (ret) { @@ -2949,11 +3005,11 @@ static void ath12k_bss_assoc(struct ath12k *ar, } static void ath12k_bss_disassoc(struct ath12k *ar, - struct ath12k_vif *arvif) + struct ath12k_link_vif *arvif) { int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", arvif->vdev_id, arvif->bssid); @@ -2996,10 +3052,10 @@ static u32 ath12k_mac_get_rate_hw_value(int bitrate) } static void ath12k_recalculate_mgmt_rate(struct ath12k *ar, - struct ieee80211_vif *vif, + struct ath12k_link_vif *arvif, struct cfg80211_chan_def *def) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); const struct ieee80211_supported_band *sband; u8 basic_rate_idx; @@ -3008,7 +3064,7 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar, u16 bitrate; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(hw->wiphy); sband = hw->wiphy->bands[def->chan->band]; basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; @@ -3033,9 +3089,19 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar, ath12k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret); } -static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif, +static int +ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u16 old_links, u16 new_links, + struct ieee80211_bss_conf *ol[IEEE80211_MLD_MAX_NUM_LINKS]) +{ + return 0; +} + +static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif, struct ieee80211_bss_conf *info) { + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); struct ath12k *ar = arvif->ar; struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); struct sk_buff *tmpl; @@ -3046,7 +3112,7 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif, if (info->fils_discovery.max_interval) { interval = info->fils_discovery.max_interval; - tmpl = ieee80211_get_fils_discovery_tmpl(hw, arvif->vif); + tmpl = ieee80211_get_fils_discovery_tmpl(hw, vif); if (tmpl) ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id, tmpl); @@ -3054,8 +3120,7 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif, unsol_bcast_probe_resp_enabled = 1; interval = info->unsol_bcast_probe_resp_interval; - tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, - arvif->vif); + tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif); if (tmpl) ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id, tmpl); @@ -3080,10 +3145,44 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif, return ret; } -static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif) +static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u64 changed) +{ + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + unsigned long links = ahvif->links_map; + struct ath12k_link_vif *arvif; + struct ath12k *ar; + u8 link_id; + + lockdep_assert_wiphy(hw->wiphy); + + if (changed & BSS_CHANGED_SSID && vif->type == NL80211_IFTYPE_AP) { + ahvif->u.ap.ssid_len = vif->cfg.ssid_len; + if (vif->cfg.ssid_len) + memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len); + } + + if (changed & BSS_CHANGED_ASSOC) { + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + if (!arvif || !arvif->ar) + continue; + + ar = arvif->ar; + + if (vif->cfg.assoc) + ath12k_bss_assoc(ar, arvif, &vif->bss_conf); + else + ath12k_bss_disassoc(ar, arvif); + } + } +} + +static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) { struct ath12k *ar = arvif->ar; - struct ieee80211_vif *vif = arvif->vif; + struct ieee80211_vif *vif = arvif->ahvif->vif; struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; enum wmi_sta_powersave_param param; enum wmi_sta_ps_mode psmode; @@ -3091,12 +3190,12 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif) int timeout; bool enable_ps; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (vif->type != NL80211_IFTYPE_STATION) return; - enable_ps = arvif->ps; + enable_ps = arvif->ahvif->ps; if (enable_ps) { psmode = WMI_STA_PS_MODE_ENABLED; param = WMI_STA_PS_PARAM_INACTIVITY_TIME; @@ -3128,11 +3227,12 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif) } static void ath12k_mac_bss_info_changed(struct ath12k *ar, - struct ath12k_vif *arvif, + struct ath12k_link_vif *arvif, struct ieee80211_bss_conf *info, u64 changed) { - struct ieee80211_vif *vif = arvif->vif; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); struct ieee80211_vif_cfg *vif_cfg = &vif->cfg; struct cfg80211_chan_def def; u32 param_id, param_value; @@ -3146,7 +3246,7 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, u8 rateidx; u32 rate; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (changed & BSS_CHANGED_BEACON_INT) { arvif->beacon_interval = info->beacon_int; @@ -3202,10 +3302,10 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, if (changed & BSS_CHANGED_SSID && vif->type == NL80211_IFTYPE_AP) { - arvif->u.ap.ssid_len = vif->cfg.ssid_len; + ahvif->u.ap.ssid_len = vif->cfg.ssid_len; if (vif->cfg.ssid_len) - memcpy(arvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len); - arvif->u.ap.hidden_ssid = info->hidden_ssid; + memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len); + ahvif->u.ap.hidden_ssid = info->hidden_ssid; } if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) @@ -3316,7 +3416,7 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, } if (changed & BSS_CHANGED_MCAST_RATE && - !ath12k_mac_vif_chan(arvif->vif, &def)) { + !ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)) { band = def.chan->band; mcast_rate = vif->bss_conf.mcast_rate[band]; @@ -3360,8 +3460,8 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, } if (changed & BSS_CHANGED_BASIC_RATES && - !ath12k_mac_vif_chan(arvif->vif, &def)) - ath12k_recalculate_mgmt_rate(ar, vif, &def); + !ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)) + ath12k_recalculate_mgmt_rate(ar, arvif, &def); if (changed & BSS_CHANGED_TWT) { if (info->twt_requester || info->twt_responder) @@ -3406,53 +3506,177 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, if (changed & BSS_CHANGED_PS && ar->ab->hw_params->supports_sta_ps) { - arvif->ps = vif_cfg->ps; + ahvif->ps = vif_cfg->ps; ath12k_mac_vif_setup_ps(arvif); } } -static struct ath12k_vif_cache *ath12k_arvif_get_cache(struct ath12k_vif *arvif) +static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif, + u8 link_id) +{ + if (!ahvif->cache[link_id]) { + ahvif->cache[link_id] = kzalloc(sizeof(*ahvif->cache[0]), GFP_KERNEL); + if (ahvif->cache[link_id]) + INIT_LIST_HEAD(&ahvif->cache[link_id]->key_conf.list); + } + + return ahvif->cache[link_id]; +} + +static void ath12k_ahvif_put_link_key_cache(struct ath12k_vif_cache *cache) { - if (!arvif->cache) - arvif->cache = kzalloc(sizeof(*arvif->cache), GFP_KERNEL); + struct ath12k_key_conf *key_conf, *tmp; - return arvif->cache; + if (!cache || list_empty(&cache->key_conf.list)) + return; + list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) { + list_del(&key_conf->list); + kfree(key_conf); + } } -static void ath12k_arvif_put_cache(struct ath12k_vif *arvif) +static void ath12k_ahvif_put_link_cache(struct ath12k_vif *ahvif, u8 link_id) { - kfree(arvif->cache); - arvif->cache = NULL; + ath12k_ahvif_put_link_key_cache(ahvif->cache[link_id]); + kfree(ahvif->cache[link_id]); + ahvif->cache[link_id] = NULL; } -static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u64 changed) +static void ath12k_mac_op_link_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u64 changed) { struct ath12k *ar; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ath12k_vif_cache *cache; + struct ath12k_link_vif *arvif; + u8 link_id = info->link_id; - ar = ath12k_get_ar_by_vif(hw, vif); + lockdep_assert_wiphy(hw->wiphy); + + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); /* if the vdev is not created on a certain radio, * cache the info to be updated later on vdev creation */ - if (!ar) { - cache = ath12k_arvif_get_cache(arvif); + if (!arvif || !arvif->is_created) { + cache = ath12k_ahvif_get_link_cache(ahvif, link_id); if (!cache) return; - arvif->cache->bss_conf_changed |= changed; + + cache->bss_conf_changed |= changed; + return; } - mutex_lock(&ar->conf_mutex); + ar = arvif->ar; ath12k_mac_bss_info_changed(ar, arvif, info, changed); +} + +static struct ath12k_link_vif *ath12k_mac_assign_link_vif(struct ath12k_hw *ah, + struct ieee80211_vif *vif, + u8 link_id) +{ + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + int i; + + lockdep_assert_wiphy(ah->hw->wiphy); + + arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]); + if (arvif) + return arvif; + + if (!vif->valid_links) { + /* Use deflink for Non-ML VIFs and mark the link id as 0 + */ + link_id = 0; + arvif = &ahvif->deflink; + } else { + /* If this is the first link arvif being created for an ML VIF + * use the preallocated deflink memory + */ + if (!ahvif->links_map) { + arvif = &ahvif->deflink; + } else { + arvif = (struct ath12k_link_vif *) + kzalloc(sizeof(struct ath12k_link_vif), GFP_KERNEL); + if (!arvif) + return NULL; + } + } + + arvif->ahvif = ahvif; + arvif->link_id = link_id; + ahvif->links_map |= BIT(link_id); + + INIT_LIST_HEAD(&arvif->list); + INIT_DELAYED_WORK(&arvif->connection_loss_work, + ath12k_mac_vif_sta_connection_loss_work); + + for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) { + arvif->bitrate_mask.control[i].legacy = 0xffffffff; + memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff, + sizeof(arvif->bitrate_mask.control[i].ht_mcs)); + memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff, + sizeof(arvif->bitrate_mask.control[i].vht_mcs)); + } + + /* Allocate Default Queue now and reassign during actual vdev create */ + vif->cab_queue = ATH12K_HW_DEFAULT_QUEUE; + for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++) + vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE; - mutex_unlock(&ar->conf_mutex); + vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; + + rcu_assign_pointer(ahvif->link[arvif->link_id], arvif); + ahvif->links_map |= BIT(link_id); + synchronize_rcu(); + return arvif; +} + +static void ath12k_mac_unassign_link_vif(struct ath12k_link_vif *arvif) +{ + struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_hw *ah = ahvif->ah; + + lockdep_assert_wiphy(ah->hw->wiphy); + + rcu_assign_pointer(ahvif->link[arvif->link_id], NULL); + synchronize_rcu(); + ahvif->links_map &= ~BIT(arvif->link_id); + + if (arvif != &ahvif->deflink) + kfree(arvif); + else + memset(arvif, 0, sizeof(*arvif)); +} + +static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, + struct ath12k_link_vif *arvif) +{ + struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar = arvif->ar; + int ret; + + lockdep_assert_wiphy(ah->hw->wiphy); + + cancel_delayed_work_sync(&arvif->connection_loss_work); + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac remove link interface (vdev %d link id %d)", + arvif->vdev_id, arvif->link_id); + + if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + ret = ath12k_peer_delete(ar, arvif->vdev_id, arvif->bssid); + if (ret) + ath12k_warn(ar->ab, "failed to submit AP self-peer removal on vdev %d link id %d: %d", + arvif->vdev_id, arvif->link_id, ret); + } + ath12k_mac_vdev_delete(ar, arvif); } static struct ath12k* @@ -3541,7 +3765,7 @@ static int ath12k_scan_stop(struct ath12k *ar) }; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); /* TODO: Fill other STOP Params */ arg.pdev_id = ar->pdev->pdev_id; @@ -3581,7 +3805,7 @@ static void ath12k_scan_abort(struct ath12k *ar) { int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); spin_lock_bh(&ar->data_lock); @@ -3616,9 +3840,9 @@ static void ath12k_scan_timeout_work(struct work_struct *work) struct ath12k *ar = container_of(work, struct ath12k, scan.timeout.work); - mutex_lock(&ar->conf_mutex); + wiphy_lock(ath12k_ar_to_hw(ar)->wiphy); ath12k_scan_abort(ar); - mutex_unlock(&ar->conf_mutex); + wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy); } static int ath12k_start_scan(struct ath12k *ar, @@ -3626,7 +3850,7 @@ static int ath12k_start_scan(struct ath12k *ar, { int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ret = ath12k_wmi_send_scan_start_cmd(ar, arg); if (ret) @@ -3655,24 +3879,50 @@ static int ath12k_start_scan(struct ath12k *ar, return 0; } +static u8 +ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar) +{ + struct ath12k_link_vif *arvif; + struct ath12k_hw *ah = ahvif->ah; + unsigned long links = ahvif->links_map; + u8 link_id; + + lockdep_assert_wiphy(ah->hw->wiphy); + + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]); + + if (!arvif || !arvif->is_created) + continue; + + if (ar == arvif->ar) + return link_id; + } + + /* input ar is not assigned to any of the links, use link id + * 0 for scan vdev creation. + */ + return 0; +} + static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) { struct ath12k_hw *ah = ath12k_hw_to_ah(hw); - struct ath12k *ar, *prev_ar; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k *ar; + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; struct cfg80211_scan_request *req = &hw_req->req; struct ath12k_wmi_scan_req_arg *arg = NULL; + u8 link_id; int ret; int i; bool create = true; - if (ah->num_radio == 1) { - WARN_ON(!arvif->is_created); - ar = ath12k_ah_to_ar(ah, 0); - goto scan; - } + lockdep_assert_wiphy(hw->wiphy); + + arvif = &ahvif->deflink; /* Since the targeted scan device could depend on the frequency * requested in the hw_req, select the corresponding radio @@ -3681,6 +3931,13 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, if (!ar) return -EINVAL; + /* check if any of the links of ML VIF is already started on + * radio(ar) correpsondig to given scan frequency and use it, + * if not use deflink(link 0) for scan purpose. + */ + link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar); + arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + /* If the vif is already assigned to a specific vdev of an ar, * check whether its already started, vdev which is started * are not allowed to switch to a new radio. @@ -3698,31 +3955,24 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, return -EINVAL; if (ar != arvif->ar) { - /* backup the previously used ar ptr, since the vdev delete - * would assign the arvif->ar to NULL after the call - */ - prev_ar = arvif->ar; - mutex_lock(&prev_ar->conf_mutex); - ret = ath12k_mac_vdev_delete(prev_ar, vif); - mutex_unlock(&prev_ar->conf_mutex); - if (ret) - ath12k_warn(prev_ar->ab, - "unable to delete scan vdev %d\n", ret); + ath12k_mac_remove_link_interface(hw, arvif); + ath12k_mac_unassign_link_vif(arvif); } else { create = false; } } if (create) { - mutex_lock(&ar->conf_mutex); - ret = ath12k_mac_vdev_create(ar, vif); - mutex_unlock(&ar->conf_mutex); + /* Previous arvif would've been cleared in radio switch block + * above, assign arvif again for create. + */ + arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + + ret = ath12k_mac_vdev_create(ar, arvif); if (ret) { ath12k_warn(ar->ab, "unable to create scan vdev %d\n", ret); return -EINVAL; } } -scan: - mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); switch (ar->scan.state) { @@ -3805,30 +4055,31 @@ exit: kfree(arg); } - mutex_unlock(&ar->conf_mutex); - return ret; } static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; struct ath12k *ar; + lockdep_assert_wiphy(hw->wiphy); + + arvif = &ahvif->deflink; + if (!arvif->is_created) return; ar = arvif->ar; - mutex_lock(&ar->conf_mutex); ath12k_scan_abort(ar); - mutex_unlock(&ar->conf_mutex); cancel_delayed_work_sync(&ar->scan.timeout); } -static int ath12k_install_key(struct ath12k_vif *arvif, +static int ath12k_install_key(struct ath12k_link_vif *arvif, struct ieee80211_key_conf *key, enum set_key_cmd cmd, const u8 *macaddr, u32 flags) @@ -3843,8 +4094,10 @@ static int ath12k_install_key(struct ath12k_vif *arvif, .key_flags = flags, .macaddr = macaddr, }; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); - lockdep_assert_held(&arvif->ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); reinit_completion(&ar->install_key_done); @@ -3895,13 +4148,13 @@ install: if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ)) return -ETIMEDOUT; - if (ether_addr_equal(macaddr, arvif->vif->addr)) - arvif->key_cipher = key->cipher; + if (ether_addr_equal(macaddr, vif->addr)) + ahvif->key_cipher = key->cipher; return ar->install_key_status ? -EINVAL : 0; } -static int ath12k_clear_peer_keys(struct ath12k_vif *arvif, +static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, const u8 *addr) { struct ath12k *ar = arvif->ar; @@ -3912,7 +4165,7 @@ static int ath12k_clear_peer_keys(struct ath12k_vif *arvif, int i; u32 flags = 0; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); spin_lock_bh(&ab->base_lock); peer = ath12k_peer_find(ab, arvif->vdev_id, addr); @@ -3944,25 +4197,31 @@ static int ath12k_clear_peer_keys(struct ath12k_vif *arvif, } static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, struct ieee80211_key_conf *key) { + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); + struct ieee80211_sta *sta = NULL; struct ath12k_base *ab = ar->ab; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct ath12k_peer *peer; - struct ath12k_sta *arsta; + struct ath12k_sta *ahsta; const u8 *peer_addr; - int ret = 0; + int ret; u32 flags = 0; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + if (arsta) + sta = ath12k_ahsta_to_sta(arsta->ahsta); if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags)) return 1; if (sta) peer_addr = sta->addr; - else if (arvif->vdev_type == WMI_VDEV_TYPE_STA) + else if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) peer_addr = vif->bss_conf.bssid; else peer_addr = vif->addr; @@ -3970,7 +4229,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, key->hw_key_idx = key->keyidx; /* the peer should not disappear in mid-way (unless FW goes awry) since - * we already hold conf_mutex. we just make sure its there now. + * we already hold wiphy lock. we just make sure its there now. */ spin_lock_bh(&ab->base_lock); peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr); @@ -3980,14 +4239,13 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, if (cmd == SET_KEY) { ath12k_warn(ab, "cannot install key for non-existent peer %pM\n", peer_addr); - ret = -EOPNOTSUPP; - goto exit; - } else { - /* if the peer doesn't exist there is no key to disable - * anymore - */ - goto exit; + return -EOPNOTSUPP; } + + /* if the peer doesn't exist there is no key to disable + * anymore + */ + return 0; } if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) @@ -3998,13 +4256,13 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags); if (ret) { ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret); - goto exit; + return ret; } ret = ath12k_dp_rx_peer_pn_replay_config(arvif, peer_addr, cmd, key); if (ret) { ath12k_warn(ab, "failed to offload PN replay detection %d\n", ret); - goto exit; + return ret; } spin_lock_bh(&ab->base_lock); @@ -4029,7 +4287,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr); if (sta) { - arsta = ath12k_sta_to_arsta(sta); + ahsta = ath12k_sta_to_ahsta(sta); switch (key->cipher) { case WLAN_CIPHER_SUITE_TKIP: @@ -4038,61 +4296,138 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: if (cmd == SET_KEY) - arsta->pn_type = HAL_PN_TYPE_WPA; + ahsta->pn_type = HAL_PN_TYPE_WPA; else - arsta->pn_type = HAL_PN_TYPE_NONE; + ahsta->pn_type = HAL_PN_TYPE_NONE; break; default: - arsta->pn_type = HAL_PN_TYPE_NONE; + ahsta->pn_type = HAL_PN_TYPE_NONE; break; } } spin_unlock_bh(&ab->base_lock); -exit: - return ret; + return 0; +} + +static int ath12k_mac_update_key_cache(struct ath12k_vif_cache *cache, + enum set_key_cmd cmd, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ath12k_key_conf *key_conf = NULL, *tmp; + + if (cmd == SET_KEY) { + key_conf = kzalloc(sizeof(*key_conf), GFP_KERNEL); + + if (!key_conf) + return -ENOMEM; + + key_conf->cmd = cmd; + key_conf->sta = sta; + key_conf->key = key; + list_add_tail(&key_conf->list, + &cache->key_conf.list); + } + if (list_empty(&cache->key_conf.list)) + return 0; + list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) { + if (key_conf->key == key) { + /* DEL key for an old SET key which driver hasn't flushed yet. + */ + list_del(&key_conf->list); + kfree(key_conf); + break; + } + } + return 0; } static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + struct ath12k_link_sta *arsta = NULL; struct ath12k_vif_cache *cache; - struct ath12k *ar; + struct ath12k_sta *ahsta; + unsigned long links; + u8 link_id; int ret; + lockdep_assert_wiphy(hw->wiphy); + /* BIP needs to be done in software */ if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC || key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || - key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) + key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) { return 1; + } if (key->keyidx > WMI_MAX_KEY_INDEX) return -ENOSPC; - ar = ath12k_get_ar_by_vif(hw, vif); - if (!ar) { - /* ar is expected to be valid when sta ptr is available */ - if (sta) { - WARN_ON_ONCE(1); - return -EINVAL; + if (sta) { + ahsta = ath12k_sta_to_ahsta(sta); + /* For an ML STA Pairwise key is same for all associated link Stations, + * hence do set key for all link STAs which are active. + */ + if (sta->mlo) { + links = ahsta->links_map; + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = wiphy_dereference(hw->wiphy, + ahvif->link[link_id]); + arsta = wiphy_dereference(hw->wiphy, + ahsta->link[link_id]); + + if (WARN_ON(!arvif || !arsta)) + /* arvif and arsta are expected to be valid when + * STA is present. + */ + continue; + + ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, + arsta, key); + if (ret) + break; + } + } else { + arsta = &ahsta->deflink; + arvif = arsta->arvif; + if (WARN_ON(!arvif)) { + ret = -EINVAL; + goto out; + } + + ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key); + } + } else { + if (key->link_id >= 0 && key->link_id < IEEE80211_MLD_MAX_NUM_LINKS) { + link_id = key->link_id; + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + } else { + link_id = 0; + arvif = &ahvif->deflink; } - cache = ath12k_arvif_get_cache(arvif); - if (!cache) - return -ENOSPC; - cache->key_conf.cmd = cmd; - cache->key_conf.key = key; - cache->key_conf.changed = true; - return 0; + if (!arvif || !arvif->is_created) { + cache = ath12k_ahvif_get_link_cache(ahvif, link_id); + if (!cache) + return -ENOSPC; + + ret = ath12k_mac_update_key_cache(cache, cmd, sta, key); + + return ret; + } + + ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, NULL, key); } - mutex_lock(&ar->conf_mutex); - ret = ath12k_mac_set_key(ar, cmd, vif, sta, key); - mutex_unlock(&ar->conf_mutex); +out: + return ret; } @@ -4111,17 +4446,18 @@ ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar, } static int -ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif, - struct ieee80211_sta *sta, +ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, const struct cfg80211_bitrate_mask *mask, enum nl80211_band band) { + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k *ar = arvif->ar; u8 vht_rate, nss; u32 rate_code; int ret, i; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); nss = 0; @@ -4157,11 +4493,12 @@ ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif, } static int ath12k_station_assoc(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, bool reassoc) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k_wmi_peer_assoc_arg peer_arg; int ret; struct cfg80211_chan_def def; @@ -4169,15 +4506,15 @@ static int ath12k_station_assoc(struct ath12k *ar, struct cfg80211_bitrate_mask *mask; u8 num_vht_rates; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return -EPERM; band = def.chan->band; mask = &arvif->bitrate_mask; - ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc); + ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, reassoc); if (peer_arg.peer_nss < 1) { ath12k_warn(ar->ab, @@ -4205,7 +4542,7 @@ static int ath12k_station_assoc(struct ath12k *ar, * Note that all other rates and NSS will be disabled for this peer. */ if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) { - ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask, + ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, band); if (ret) return ret; @@ -4234,7 +4571,7 @@ static int ath12k_station_assoc(struct ath12k *ar, } if (sta->wme && sta->uapsd_queues) { - ret = ath12k_peer_assoc_qos_ap(ar, arvif, sta); + ret = ath12k_peer_assoc_qos_ap(ar, arvif, arsta); if (ret) { ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n", sta->addr, arvif->vdev_id, ret); @@ -4246,13 +4583,13 @@ static int ath12k_station_assoc(struct ath12k *ar, } static int ath12k_station_disassoc(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (!sta->wme) { arvif->num_legacy_stations--; @@ -4270,11 +4607,10 @@ static int ath12k_station_disassoc(struct ath12k *ar, return 0; } -static void ath12k_sta_rc_update_wk(struct work_struct *wk) +static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk) { struct ath12k *ar; - struct ath12k_vif *arvif; - struct ath12k_sta *arsta; + struct ath12k_link_vif *arvif; struct ieee80211_sta *sta; struct cfg80211_chan_def def; enum nl80211_band band; @@ -4285,13 +4621,18 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) const struct cfg80211_bitrate_mask *mask; struct ath12k_wmi_peer_assoc_arg peer_arg; enum wmi_phy_mode peer_phymode; + struct ath12k_link_sta *arsta; + struct ieee80211_vif *vif; - arsta = container_of(wk, struct ath12k_sta, update_wk); - sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); + lockdep_assert_wiphy(wiphy); + + arsta = container_of(wk, struct ath12k_link_sta, update_wk); + sta = ath12k_ahsta_to_sta(arsta->ahsta); arvif = arsta->arvif; + vif = ath12k_ahvif_to_vif(arvif->ahvif); ar = arvif->ar; - if (WARN_ON(ath12k_mac_vif_chan(arvif->vif, &def))) + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) return; band = def.chan->band; @@ -4310,14 +4651,12 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) spin_unlock_bh(&ar->data_lock); - mutex_lock(&ar->conf_mutex); - nss = max_t(u32, 1, nss); nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask), ath12k_mac_max_vht_nss(vht_mcs_mask))); if (changed & IEEE80211_RC_BW_CHANGED) { - ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg); + ath12k_peer_assoc_h_phymode(ar, arvif, arsta, &peer_arg); peer_phymode = peer_arg.peer_phymode; if (bw > bw_prev) { @@ -4334,7 +4673,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) if (err) { ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n", sta->addr, peer_phymode, err); - goto err_rc_bw_changed; + return; } err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, WMI_PEER_CHWIDTH, @@ -4355,7 +4694,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) if (err) { ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n", sta->addr, bw, err); - goto err_rc_bw_changed; + return; } err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, WMI_PEER_PHYMODE, @@ -4405,14 +4744,14 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) * across HT/VHT and for multiple VHT MCS support. */ if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) { - ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask, + ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, band); } else { /* If the peer is non-VHT or no fixed VHT rate * is provided in the new bitrate mask we set the * other rates using peer_assoc command. */ - ath12k_peer_assoc_prepare(ar, arvif->vif, sta, + ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, true); err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg); @@ -4425,18 +4764,17 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) sta->addr, arvif->vdev_id); } } -err_rc_bw_changed: - mutex_unlock(&ar->conf_mutex); } -static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif, - struct ieee80211_sta *sta) +static int ath12k_mac_inc_num_stations(struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) { + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k *ar = arvif->ar; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) + if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) return 0; if (ar->num_stations >= ar->max_num_stations) @@ -4447,38 +4785,38 @@ static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif, return 0; } -static void ath12k_mac_dec_num_stations(struct ath12k_vif *arvif, - struct ieee80211_sta *sta) +static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) { + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k *ar = arvif->ar; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) + if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) return; ar->num_stations--; } static int ath12k_mac_station_add(struct ath12k *ar, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) { struct ath12k_base *ab = ar->ab; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); + struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta); struct ath12k_wmi_peer_create_arg peer_param; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - ret = ath12k_mac_inc_num_stations(arvif, sta); + ret = ath12k_mac_inc_num_stations(arvif, arsta); if (ret) { ath12k_warn(ab, "refusing to associate station: too many connected already (%d)\n", ar->max_num_stations); goto exit; } - arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL); if (!arsta->rx_stats) { ret = -ENOMEM; @@ -4519,7 +4857,7 @@ static int ath12k_mac_station_add(struct ath12k *ar, if (ab->hw_params->vdev_start_delay && !arvif->is_started && - arvif->vdev_type != WMI_VDEV_TYPE_AP) { + arvif->ahvif->vdev_type != WMI_VDEV_TYPE_AP) { ret = ath12k_start_vdev_delay(ar, arvif); if (ret) { ath12k_warn(ab, "failed to delay vdev start: %d\n", ret); @@ -4532,7 +4870,7 @@ static int ath12k_mac_station_add(struct ath12k *ar, free_peer: ath12k_peer_delete(ar, arvif->vdev_id, sta->addr); dec_num_station: - ath12k_mac_dec_num_stations(arvif, sta); + ath12k_mac_dec_num_stations(arvif, arsta); exit: return ret; } @@ -4574,16 +4912,18 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta); struct ath12k *ar; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); + struct ath12k_link_vif *arvif; + struct ath12k_link_sta *arsta; struct ath12k_peer *peer; int ret = 0; - /* cancel must be done outside the mutex to avoid deadlock */ - if ((old_state == IEEE80211_STA_NONE && - new_state == IEEE80211_STA_NOTEXIST)) - cancel_work_sync(&arsta->update_wk); + lockdep_assert_wiphy(hw->wiphy); + + arvif = &ahvif->deflink; + arsta = &ahsta->deflink; ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -4591,21 +4931,28 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, return -EINVAL; } - mutex_lock(&ar->conf_mutex); - if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { memset(arsta, 0, sizeof(*arsta)); + rcu_assign_pointer(ahsta->link[0], arsta); + /* TODO use appropriate link id once MLO support is added */ + arsta->link_id = ATH12K_DEFAULT_LINK_ID; + ahsta->links_map = BIT(arsta->link_id); + arsta->ahsta = ahsta; arsta->arvif = arvif; - INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk); + wiphy_work_init(&arsta->update_wk, ath12k_sta_rc_update_wk); + + synchronize_rcu(); - ret = ath12k_mac_station_add(ar, vif, sta); + ret = ath12k_mac_station_add(ar, arvif, arsta); if (ret) ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n", sta->addr, arvif->vdev_id); } else if ((old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST)) { - if (arvif->vdev_type == WMI_VDEV_TYPE_STA) { + wiphy_work_cancel(hw->wiphy, &arsta->update_wk); + + if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) { ath12k_bss_disassoc(ar, arvif); ret = ath12k_mac_vdev_stop(arvif); if (ret) @@ -4622,7 +4969,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n", sta->addr, arvif->vdev_id); - ath12k_mac_dec_num_stations(arvif, sta); + ath12k_mac_dec_num_stations(arvif, arsta); spin_lock_bh(&ar->ab->base_lock); peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); if (peer && peer->sta == sta) { @@ -4637,12 +4984,20 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, kfree(arsta->rx_stats); arsta->rx_stats = NULL; + + if (arsta->link_id < IEEE80211_MLD_MAX_NUM_LINKS) { + rcu_assign_pointer(ahsta->link[arsta->link_id], NULL); + synchronize_rcu(); + ahsta->links_map &= ~(BIT(arsta->link_id)); + arsta->link_id = ATH12K_INVALID_LINK_ID; + arsta->ahsta = NULL; + } } else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_ADHOC)) { - ret = ath12k_station_assoc(ar, vif, sta, false); + ret = ath12k_station_assoc(ar, arvif, arsta, false); if (ret) ath12k_warn(ar->ab, "Failed to associate station: %pM\n", sta->addr); @@ -4686,14 +5041,12 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_ADHOC)) { - ret = ath12k_station_disassoc(ar, vif, sta); + ret = ath12k_station_disassoc(ar, arvif, arsta); if (ret) ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n", sta->addr); } - mutex_unlock(&ar->conf_mutex); - return ret; } @@ -4703,25 +5056,32 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw, { struct ath12k_hw *ah = ath12k_hw_to_ah(hw); struct ath12k *ar; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; int ret; s16 txpwr; + lockdep_assert_wiphy(hw->wiphy); + + arvif = &ahvif->deflink; + if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) { txpwr = 0; } else { txpwr = sta->deflink.txpwr.power; - if (!txpwr) - return -EINVAL; + if (!txpwr) { + ret = -EINVAL; + goto out; + } } - if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL) - return -EINVAL; + if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL) { + ret = -EINVAL; + goto out; + } ar = ath12k_ah_to_ar(ah, 0); - mutex_lock(&ar->conf_mutex); - ret = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, WMI_PEER_USE_FIXED_PWR, txpwr); if (ret) { @@ -4731,20 +5091,26 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw, } out: - mutex_unlock(&ar->conf_mutex); return ret; } static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct ath12k *ar; - struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_sta *arsta; + struct ath12k_link_vif *arvif; struct ath12k_peer *peer; u32 bw, smps; + /* TODO: use proper link id once link sta specific rc update support is + * available in mac80211. + */ + u8 link_id = ATH12K_DEFAULT_LINK_ID; ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -4752,11 +5118,27 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, return; } + rcu_read_lock(); + arvif = rcu_dereference(ahvif->link[link_id]); + if (!arvif) { + ath12k_warn(ar->ab, "mac sta rc update failed to fetch link vif on link id %u for peer %pM\n", + link_id, sta->addr); + rcu_read_unlock(); + return; + } + arsta = rcu_dereference(ahsta->link[link_id]); + if (!arsta) { + rcu_read_unlock(); + ath12k_warn(ar->ab, "mac sta rc update failed to fetch link sta on link id %u for peer %pM\n", + link_id, sta->addr); + return; + } spin_lock_bh(&ar->ab->base_lock); peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); if (!peer) { spin_unlock_bh(&ar->ab->base_lock); + rcu_read_unlock(); ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n", sta->addr, arvif->vdev_id); return; @@ -4808,17 +5190,20 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, spin_unlock_bh(&ar->data_lock); - ieee80211_queue_work(hw, &arsta->update_wk); + wiphy_work_queue(hw->wiphy, &arsta->update_wk); + + rcu_read_unlock(); } -static int ath12k_conf_tx_uapsd(struct ath12k_vif *arvif, +static int ath12k_conf_tx_uapsd(struct ath12k_link_vif *arvif, u16 ac, bool enable) { struct ath12k *ar = arvif->ar; + struct ath12k_vif *ahvif = arvif->ahvif; u32 value; int ret; - if (arvif->vdev_type != WMI_VDEV_TYPE_STA) + if (ahvif->vdev_type != WMI_VDEV_TYPE_STA) return 0; switch (ac) { @@ -4841,19 +5226,19 @@ static int ath12k_conf_tx_uapsd(struct ath12k_vif *arvif, } if (enable) - arvif->u.sta.uapsd |= value; + ahvif->u.sta.uapsd |= value; else - arvif->u.sta.uapsd &= ~value; + ahvif->u.sta.uapsd &= ~value; ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, WMI_STA_PS_PARAM_UAPSD, - arvif->u.sta.uapsd); + ahvif->u.sta.uapsd); if (ret) { ath12k_warn(ar->ab, "could not set uapsd params %d\n", ret); goto exit; } - if (arvif->u.sta.uapsd) + if (ahvif->u.sta.uapsd) value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD; else value = WMI_STA_PS_RX_WAKE_POLICY_WAKE; @@ -4868,8 +5253,7 @@ exit: return ret; } -static int ath12k_mac_conf_tx(struct ath12k_vif *arvif, - unsigned int link_id, u16 ac, +static int ath12k_mac_conf_tx(struct ath12k_link_vif *arvif, u16 ac, const struct ieee80211_tx_queue_params *params) { struct wmi_wmm_params_arg *p = NULL; @@ -4877,7 +5261,7 @@ static int ath12k_mac_conf_tx(struct ath12k_vif *arvif, struct ath12k_base *ab = ar->ab; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); switch (ac) { case IEEE80211_AC_VO: @@ -4926,26 +5310,30 @@ static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw, unsigned int link_id, u16 ac, const struct ieee80211_tx_queue_params *params) { - struct ath12k *ar; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct ath12k_vif_cache *cache = arvif->cache; + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + struct ath12k_vif_cache *cache; int ret; - ar = ath12k_get_ar_by_vif(hw, vif); - if (!ar) { - /* cache the info and apply after vdev is created */ - cache = ath12k_arvif_get_cache(arvif); + lockdep_assert_wiphy(hw->wiphy); + + if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) + return -EINVAL; + + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + if (!arvif || !arvif->is_created) { + cache = ath12k_ahvif_get_link_cache(ahvif, link_id); if (!cache) return -ENOSPC; + cache->tx_conf.changed = true; cache->tx_conf.ac = ac; cache->tx_conf.tx_queue_params = *params; + return 0; } - mutex_lock(&ar->conf_mutex); - ret = ath12k_mac_conf_tx(arvif, link_id, ac, params); - mutex_unlock(&ar->conf_mutex); + ret = ath12k_mac_conf_tx(arvif, ac, params); return ret; } @@ -5016,10 +5404,11 @@ ath12k_create_ht_cap(struct ath12k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask return ht_cap; } -static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif) +static int ath12k_mac_set_txbf_conf(struct ath12k_link_vif *arvif) { u32 value = 0; struct ath12k *ar = arvif->ar; + struct ath12k_vif *ahvif = arvif->ahvif; int nsts; int sound_dim; u32 vht_cap = ar->pdev->cap.vht_cap; @@ -5047,7 +5436,7 @@ static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif) value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER; if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) && - arvif->vdev_type == WMI_VDEV_TYPE_AP) + ahvif->vdev_type == WMI_VDEV_TYPE_AP) value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER; } @@ -5055,7 +5444,7 @@ static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif) value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE; if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) && - arvif->vdev_type == WMI_VDEV_TYPE_STA) + ahvif->vdev_type == WMI_VDEV_TYPE_STA) value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE; } @@ -5612,7 +6001,7 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant) struct ath12k_hw *ah = ath12k_ar_to_ah(ar); int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (ath12k_check_chain_mask(ar, tx_ant, true)) return -EINVAL; @@ -5716,7 +6105,7 @@ static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx) return 0; } -static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif, +static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arvif, struct sk_buff *skb) { struct ath12k_base *ab = ar->ab; @@ -5784,7 +6173,8 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) { struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work); struct ath12k_skb_cb *skb_cb; - struct ath12k_vif *arvif; + struct ath12k_vif *ahvif; + struct ath12k_link_vif *arvif; struct sk_buff *skb; int ret; @@ -5796,8 +6186,8 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) continue; } - arvif = ath12k_vif_to_arvif(skb_cb->vif); - + ahvif = ath12k_vif_to_ahvif(skb_cb->vif); + arvif = &ahvif->deflink; if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) { ret = ath12k_mac_mgmt_tx_wmi(ar, arvif, skb); if (ret) { @@ -5852,18 +6242,18 @@ static void ath12k_mac_add_p2p_noa_ie(struct ath12k *ar, struct sk_buff *skb, bool is_prb_rsp) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); if (likely(!is_prb_rsp)) return; spin_lock_bh(&ar->data_lock); - if (arvif->u.ap.noa_data && - !pskb_expand_head(skb, 0, arvif->u.ap.noa_len, + if (ahvif->u.ap.noa_data && + !pskb_expand_head(skb, 0, ahvif->u.ap.noa_len, GFP_ATOMIC)) - skb_put_data(skb, arvif->u.ap.noa_data, - arvif->u.ap.noa_len); + skb_put_data(skb, ahvif->u.ap.noa_data, + ahvif->u.ap.noa_len); spin_unlock_bh(&ar->data_lock); } @@ -5875,7 +6265,8 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif = &ahvif->deflink; struct ath12k *ar = arvif->ar; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_key_conf *key = info->control.hw_key; @@ -5939,8 +6330,7 @@ static int ath12k_mac_start(struct ath12k *ar) int ret; lockdep_assert_held(&ah->hw_mutex); - - mutex_lock(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1, pdev->pdev_id); @@ -6025,14 +6415,11 @@ static int ath12k_mac_start(struct ath12k *ar) } } - mutex_unlock(&ar->conf_mutex); - rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], &ab->pdevs[ar->pdev_idx]); return 0; err: - mutex_unlock(&ar->conf_mutex); return ret; } @@ -6052,6 +6439,8 @@ static int ath12k_mac_op_start(struct ieee80211_hw *hw) struct ath12k *ar; int ret, i; + lockdep_assert_wiphy(hw->wiphy); + ath12k_drain_tx(ah); guard(mutex)(&ah->hw_mutex); @@ -6158,15 +6547,14 @@ static void ath12k_mac_stop(struct ath12k *ar) int ret; lockdep_assert_held(&ah->hw_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - mutex_lock(&ar->conf_mutex); ret = ath12k_mac_config_mon_status_default(ar, false); if (ret && (ret != -EOPNOTSUPP)) ath12k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n", ret); clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); - mutex_unlock(&ar->conf_mutex); cancel_delayed_work_sync(&ar->scan.timeout); cancel_work_sync(&ar->regd_update_work); @@ -6192,6 +6580,8 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend) struct ath12k *ar; int i; + lockdep_assert_wiphy(hw->wiphy); + ath12k_drain_tx(ah); mutex_lock(&ah->hw_mutex); @@ -6205,7 +6595,7 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend) } static u8 -ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif) +ath12k_mac_get_vdev_stats_id(struct ath12k_link_vif *arvif) { struct ath12k_base *ab = arvif->ar->ab; u8 vdev_stats_id = 0; @@ -6227,19 +6617,22 @@ ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif) return vdev_stats_id; } -static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_vif *arvif, +static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif, u32 *flags, u32 *tx_vdev_id) { - struct ieee80211_vif *tx_vif = arvif->vif->mbssid_tx_vif; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *tx_vif = ahvif->vif->mbssid_tx_vif; struct ath12k *ar = arvif->ar; - struct ath12k_vif *tx_arvif; + struct ath12k_link_vif *tx_arvif; + struct ath12k_vif *tx_ahvif; if (!tx_vif) return 0; - tx_arvif = ath12k_vif_to_arvif(tx_vif); + tx_ahvif = ath12k_vif_to_ahvif(tx_vif); + tx_arvif = &tx_ahvif->deflink; - if (arvif->vif->bss_conf.nontransmitted) { + if (ahvif->vif->bss_conf.nontransmitted) { if (ar->ah->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) return -EINVAL; @@ -6251,22 +6644,23 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_vif *arvif, return -EINVAL; } - if (arvif->vif->bss_conf.ema_ap) + if (ahvif->vif->bss_conf.ema_ap) *flags |= WMI_VDEV_MBSSID_FLAGS_EMA_MODE; return 0; } -static int ath12k_mac_setup_vdev_create_arg(struct ath12k_vif *arvif, +static int ath12k_mac_setup_vdev_create_arg(struct ath12k_link_vif *arvif, struct ath12k_wmi_vdev_create_arg *arg) { struct ath12k *ar = arvif->ar; struct ath12k_pdev *pdev = ar->pdev; + struct ath12k_vif *ahvif = arvif->ahvif; int ret; arg->if_id = arvif->vdev_id; - arg->type = arvif->vdev_type; - arg->subtype = arvif->vdev_subtype; + arg->type = ahvif->vdev_type; + arg->subtype = ahvif->vdev_subtype; arg->pdev_id = pdev->pdev_id; arg->mbssid_flags = WMI_VDEV_MBSSID_FLAGS_NON_MBSSID_AP; @@ -6333,14 +6727,15 @@ ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype) } static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar, - struct ath12k_vif *arvif) + struct ath12k_link_vif *arvif) { u32 param_id, param_value; struct ath12k_base *ab = ar->ab; + struct ath12k_vif *ahvif = arvif->ahvif; int ret; param_id = WMI_VDEV_PARAM_SET_HEMU_MODE; - param_value = ath12k_mac_prepare_he_mode(ar->pdev, arvif->vif->type); + param_value = ath12k_mac_prepare_he_mode(ar->pdev, ahvif->vif->type); ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param_id, param_value); if (ret) { @@ -6363,9 +6758,10 @@ static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar, return ret; } -static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif) +static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif) { - struct ieee80211_vif *vif = arvif->vif; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); struct ath12k *ar = arvif->ar; struct ath12k_base *ab = ar->ab; u32 param_id, param_value; @@ -6378,14 +6774,14 @@ static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif) IEEE80211_OFFLOAD_DECAP_ENABLED); if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) - arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET; + ahvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET; else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) - arvif->tx_encap_type = ATH12K_HW_TXRX_RAW; + ahvif->tx_encap_type = ATH12K_HW_TXRX_RAW; else - arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI; + ahvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI; ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, - param_id, arvif->tx_encap_type); + param_id, ahvif->tx_encap_type); if (ret) { ath12k_warn(ab, "failed to set vdev %d tx encap mode: %d\n", arvif->vdev_id, ret); @@ -6412,57 +6808,86 @@ static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif) static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + unsigned long links; + int link_id; - ath12k_mac_update_vif_offload(arvif); + lockdep_assert_wiphy(hw->wiphy); + + if (vif->valid_links) { + links = vif->valid_links; + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + if (!(arvif && arvif->ar)) + continue; + + ath12k_mac_update_vif_offload(arvif); + } + + return; + } + + ath12k_mac_update_vif_offload(&ahvif->deflink); } -static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) +int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) { struct ath12k_hw *ah = ar->ah; struct ath12k_base *ab = ar->ab; struct ieee80211_hw *hw = ah->hw; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); struct ath12k_wmi_vdev_create_arg vdev_arg = {0}; struct ath12k_wmi_peer_create_arg peer_param; + struct ieee80211_bss_conf *link_conf; u32 param_id, param_value; u16 nss; int i; int ret, vdev_id; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(hw->wiphy); + + link_conf = wiphy_dereference(hw->wiphy, vif->link_conf[arvif->link_id]); + if (!link_conf) { + ath12k_warn(ar->ab, "unable to access bss link conf in vdev create for vif %pM link %u\n", + vif->addr, arvif->link_id); + return -ENOLINK; + } + + memcpy(arvif->bssid, link_conf->addr, ETH_ALEN); arvif->ar = ar; vdev_id = __ffs64(ab->free_vdev_map); arvif->vdev_id = vdev_id; - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; + ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; switch (vif->type) { case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: - arvif->vdev_type = WMI_VDEV_TYPE_STA; + ahvif->vdev_type = WMI_VDEV_TYPE_STA; if (vif->p2p) - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT; + ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT; break; case NL80211_IFTYPE_MESH_POINT: - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; + ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; fallthrough; case NL80211_IFTYPE_AP: - arvif->vdev_type = WMI_VDEV_TYPE_AP; + ahvif->vdev_type = WMI_VDEV_TYPE_AP; if (vif->p2p) - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO; + ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO; break; case NL80211_IFTYPE_MONITOR: - arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; + ahvif->vdev_type = WMI_VDEV_TYPE_MONITOR; ar->monitor_vdev_id = vdev_id; break; case NL80211_IFTYPE_P2P_DEVICE: - arvif->vdev_type = WMI_VDEV_TYPE_STA; - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; + ahvif->vdev_type = WMI_VDEV_TYPE_STA; + ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; break; default: WARN_ON(1); @@ -6470,7 +6895,7 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) } ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev create id %d type %d subtype %d map %llx\n", - arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype, + arvif->vdev_id, ahvif->vdev_type, ahvif->vdev_subtype, ab->free_vdev_map); vif->cab_queue = arvif->vdev_id % (ATH12K_HW_MAX_QUEUES - 1); @@ -6484,11 +6909,11 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) goto err; } - ret = ath12k_wmi_vdev_create(ar, vif->addr, &vdev_arg); + ret = ath12k_wmi_vdev_create(ar, arvif->bssid, &vdev_arg); if (ret) { ath12k_warn(ab, "failed to create WMI vdev %d: %d\n", arvif->vdev_id, ret); - goto err; + return ret; } ar->num_created_vdevs++; @@ -6513,10 +6938,10 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) goto err_vdev_del; } - switch (arvif->vdev_type) { + switch (ahvif->vdev_type) { case WMI_VDEV_TYPE_AP: peer_param.vdev_id = arvif->vdev_id; - peer_param.peer_addr = vif->addr; + peer_param.peer_addr = arvif->bssid; peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; ret = ath12k_peer_create(ar, arvif, NULL, &peer_param); if (ret) { @@ -6589,29 +7014,28 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) } ath12k_dp_vdev_tx_attach(ar, arvif); - if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled) ath12k_mac_monitor_vdev_create(ar); - arvif->ar = ar; return ret; err_peer_del: - if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { reinit_completion(&ar->peer_delete_done); - ret = ath12k_wmi_send_peer_delete_cmd(ar, vif->addr, + ret = ath12k_wmi_send_peer_delete_cmd(ar, arvif->bssid, arvif->vdev_id); if (ret) { ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", - arvif->vdev_id, vif->addr); + arvif->vdev_id, arvif->bssid); goto err; } ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, - vif->addr); + arvif->bssid); if (ret) - goto err; + /* KVALO: why not goto err? */ + return ret; ar->num_peers--; } @@ -6633,21 +7057,56 @@ err: return ret; } -static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif) +static void ath12k_mac_vif_flush_key_cache(struct ath12k_link_vif *arvif) +{ + struct ath12k_key_conf *key_conf, *tmp; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_hw *ah = ahvif->ah; + struct ath12k_sta *ahsta; + struct ath12k_link_sta *arsta; + struct ath12k_vif_cache *cache = ahvif->cache[arvif->link_id]; + int ret; + + lockdep_assert_wiphy(ah->hw->wiphy); + + list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) { + arsta = NULL; + if (key_conf->sta) { + ahsta = ath12k_sta_to_ahsta(key_conf->sta); + arsta = wiphy_dereference(ah->hw->wiphy, + ahsta->link[arvif->link_id]); + if (!arsta) + goto free_cache; + } + + ret = ath12k_mac_set_key(arvif->ar, key_conf->cmd, + arvif, arsta, + key_conf->key); + if (ret) + ath12k_warn(arvif->ar->ab, "unable to apply set key param to vdev %d ret %d\n", + arvif->vdev_id, ret); +free_cache: + list_del(&key_conf->list); + kfree(key_conf); + } +} + +static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ath12k_link_vif *arvif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct ath12k_vif_cache *cache = arvif->cache; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); + struct ath12k_vif_cache *cache = ahvif->cache[arvif->link_id]; struct ath12k_base *ab = ar->ab; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (!cache) return; if (cache->tx_conf.changed) { - ret = ath12k_mac_conf_tx(arvif, 0, cache->tx_conf.ac, + ret = ath12k_mac_conf_tx(arvif, cache->tx_conf.ac, &cache->tx_conf.tx_queue_params); if (ret) ath12k_warn(ab, @@ -6660,26 +7119,25 @@ static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif cache->bss_conf_changed); } - if (cache->key_conf.changed) { - ret = ath12k_mac_set_key(ar, cache->key_conf.cmd, vif, NULL, - cache->key_conf.key); - if (ret) - ath12k_warn(ab, "unable to apply set key param to vdev %d ret %d\n", - arvif->vdev_id, ret); - } - ath12k_arvif_put_cache(arvif); + if (!list_empty(&cache->key_conf.list)) + ath12k_mac_vif_flush_key_cache(arvif); + + ath12k_ahvif_put_link_cache(ahvif, arvif->link_id); } static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, + struct ath12k_link_vif *arvif, struct ieee80211_chanctx_conf *ctx) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); struct ath12k_hw *ah = hw->priv; - struct ath12k *ar, *prev_ar; + struct ath12k *ar; struct ath12k_base *ab; + u8 link_id = arvif->link_id; int ret; + lockdep_assert_wiphy(hw->wiphy); + if (ah->num_radio == 1) ar = ah->radio; else if (ctx) @@ -6708,27 +7166,20 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw, if (WARN_ON(arvif->is_started)) return NULL; - /* backup the previously used ar ptr since arvif->ar would - * be set to NULL after vdev delete is done - */ - prev_ar = arvif->ar; - mutex_lock(&prev_ar->conf_mutex); - ret = ath12k_mac_vdev_delete(prev_ar, vif); - - if (ret) - ath12k_warn(prev_ar->ab, "unable to delete vdev %d\n", - ret); - mutex_unlock(&prev_ar->conf_mutex); + ath12k_mac_remove_link_interface(hw, arvif); + ath12k_mac_unassign_link_vif(arvif); } } ab = ar->ab; - mutex_lock(&ar->conf_mutex); - if (arvif->is_created) goto flush; + /* Assign arvif again here since previous radio switch block + * would've unassigned and cleared it. + */ + arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); if (vif->type == NL80211_IFTYPE_AP && ar->num_peers > (ar->max_num_peers - 1)) { ath12k_warn(ab, "failed to create vdev due to insufficient peer entry resource in firmware\n"); @@ -6741,7 +7192,7 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw, goto unlock; } - ret = ath12k_mac_vdev_create(ar, vif); + ret = ath12k_mac_vdev_create(ar, arvif); if (ret) { ath12k_warn(ab, "failed to create vdev %pM ret %d", vif->addr, ret); goto unlock; @@ -6752,21 +7203,27 @@ flush: * add_interface(), Apply any parameters for the vdev which were received * after add_interface, corresponding to this vif. */ - ath12k_mac_vif_cache_flush(ar, vif); + ath12k_mac_vif_cache_flush(ar, arvif); unlock: - mutex_unlock(&ar->conf_mutex); return arvif->ar; } static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_hw *ah = ath12k_hw_to_ah(hw); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; int i; - memset(arvif, 0, sizeof(*arvif)); + lockdep_assert_wiphy(hw->wiphy); - arvif->vif = vif; + memset(ahvif, 0, sizeof(*ahvif)); + + ahvif->ah = ah; + ahvif->vif = vif; + arvif = &ahvif->deflink; + arvif->ahvif = ahvif; INIT_LIST_HEAD(&arvif->list); INIT_DELAYED_WORK(&arvif->connection_loss_work, @@ -6786,13 +7243,14 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw, vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE; vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; - - /* For single radio wiphy(i.e ah->num_radio is 1), create the vdev - * during add_interface itself, for multi radio wiphy, defer the vdev - * creation until channel_assign to determine the radio on which the - * vdev needs to be created + /* For non-ml vifs, vif->addr is the actual vdev address but for + * ML vif link(link BSSID) address is the vdev address and it can be a + * different one from vif->addr (i.e ML address). + * Defer vdev creation until assign_chanctx or hw_scan is initiated as driver + * will not know if this interface is an ML vif at this point. */ - ath12k_mac_assign_vif_to_vdev(hw, vif, NULL); + ath12k_mac_assign_vif_to_vdev(hw, arvif, NULL); + return 0; } @@ -6821,14 +7279,16 @@ static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif } } -static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif) +static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arvif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); struct ath12k_base *ab = ar->ab; unsigned long time_left; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + reinit_completion(&ar->vdev_delete_done); ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id); @@ -6849,7 +7309,7 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif) ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); ar->num_created_vdevs--; - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ar->monitor_vdev_id = -1; ar->monitor_vdev_created = false; } else if (ar->monitor_vdev_created && !ar->monitor_started) { @@ -6865,7 +7325,7 @@ err_vdev_del: spin_unlock_bh(&ar->data_lock); ath12k_peer_cleanup(ar, arvif->vdev_id); - ath12k_arvif_put_cache(arvif); + ath12k_ahvif_put_link_cache(ahvif, arvif->link_id); idr_for_each(&ar->txmgmt_idr, ath12k_mac_vif_txmgmt_idr_remove, vif); @@ -6886,39 +7346,24 @@ err_vdev_del: static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct ath12k_base *ab; - struct ath12k *ar; - int ret; + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + u8 link_id; - if (!arvif->is_created) { + lockdep_assert_wiphy(hw->wiphy); + + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { /* if we cached some config but never received assign chanctx, * free the allocated cache. */ - ath12k_arvif_put_cache(arvif); - return; - } - - ar = arvif->ar; - ab = ar->ab; - - cancel_delayed_work_sync(&arvif->connection_loss_work); - - mutex_lock(&ar->conf_mutex); - - ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n", - arvif->vdev_id); + ath12k_ahvif_put_link_cache(ahvif, link_id); + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + if (!arvif || !arvif->is_created) + continue; - if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { - ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr); - if (ret) - ath12k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n", - arvif->vdev_id, ret); + ath12k_mac_remove_link_interface(hw, arvif); + ath12k_mac_unassign_link_vif(arvif); } - - ath12k_mac_vdev_delete(ar, vif); - - mutex_unlock(&ar->conf_mutex); } /* FIXME: Has to be verified. */ @@ -6937,7 +7382,7 @@ static void ath12k_mac_configure_filter(struct ath12k *ar, bool reset_flag; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ar->filter_flags = total_flags; @@ -6962,14 +7407,12 @@ static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw, struct ath12k_hw *ah = ath12k_hw_to_ah(hw); struct ath12k *ar; - ar = ath12k_ah_to_ar(ah, 0); + lockdep_assert_wiphy(hw->wiphy); - mutex_lock(&ar->conf_mutex); + ar = ath12k_ah_to_ar(ah, 0); *total_flags &= SUPPORTED_FILTERS; ath12k_mac_configure_filter(ar, *total_flags); - - mutex_unlock(&ar->conf_mutex); } static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) @@ -6979,11 +7422,11 @@ static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 * struct ath12k *ar; int i; + lockdep_assert_wiphy(hw->wiphy); + for_each_ar(ah, ar, i) { - mutex_lock(&ar->conf_mutex); antennas_rx = max_t(u32, antennas_rx, ar->cfg_rx_chainmask); antennas_tx = max_t(u32, antennas_tx, ar->cfg_tx_chainmask); - mutex_unlock(&ar->conf_mutex); } *tx_ant = antennas_tx; @@ -6999,10 +7442,10 @@ static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx int ret = 0; int i; + lockdep_assert_wiphy(hw->wiphy); + for_each_ar(ah, ar, i) { - mutex_lock(&ar->conf_mutex); ret = __ath12k_set_antenna(ar, tx_ant, rx_ant); - mutex_unlock(&ar->conf_mutex); if (ret) break; } @@ -7010,13 +7453,13 @@ static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx return ret; } -static int ath12k_mac_ampdu_action(struct ath12k_vif *arvif, +static int ath12k_mac_ampdu_action(struct ath12k_link_vif *arvif, struct ieee80211_ampdu_params *params) { struct ath12k *ar = arvif->ar; int ret = -EINVAL; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); switch (params->action) { case IEEE80211_AMPDU_RX_START: @@ -7046,19 +7489,20 @@ static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw, { struct ath12k_hw *ah = ath12k_hw_to_ah(hw); struct ath12k *ar; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; int ret = -EINVAL; + lockdep_assert_wiphy(hw->wiphy); + ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) return -EINVAL; ar = ath12k_ah_to_ar(ah, 0); + arvif = &ahvif->deflink; - mutex_lock(&ar->conf_mutex); ret = ath12k_mac_ampdu_action(arvif, params); - mutex_unlock(&ar->conf_mutex); - if (ret) ath12k_warn(ar->ab, "pdev idx %d unable to perform ampdu action %d ret %d\n", ar->pdev_idx, params->action, ret); @@ -7072,6 +7516,8 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw, struct ath12k *ar; struct ath12k_base *ab; + lockdep_assert_wiphy(hw->wiphy); + ar = ath12k_get_ar_by_ctx(hw, ctx); if (!ar) return -EINVAL; @@ -7082,8 +7528,6 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw, "mac chanctx add freq %u width %d ptr %p\n", ctx->def.chan->center_freq, ctx->def.width, ctx); - mutex_lock(&ar->conf_mutex); - spin_lock_bh(&ar->data_lock); /* TODO: In case of multiple channel context, populate rx_channel from * Rx PPDU desc information. @@ -7091,8 +7535,6 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw, ar->rx_channel = ctx->def.chan; spin_unlock_bh(&ar->data_lock); - mutex_unlock(&ar->conf_mutex); - return 0; } @@ -7102,6 +7544,8 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw, struct ath12k *ar; struct ath12k_base *ab; + lockdep_assert_wiphy(hw->wiphy); + ar = ath12k_get_ar_by_ctx(hw, ctx); if (!ar) return; @@ -7112,16 +7556,12 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw, "mac chanctx remove freq %u width %d ptr %p\n", ctx->def.chan->center_freq, ctx->def.width, ctx); - mutex_lock(&ar->conf_mutex); - spin_lock_bh(&ar->data_lock); /* TODO: In case of there is one more channel context left, populate * rx_channel with the channel of that remaining channel context. */ ar->rx_channel = NULL; spin_unlock_bh(&ar->data_lock); - - mutex_unlock(&ar->conf_mutex); } static enum wmi_phy_mode @@ -7188,7 +7628,7 @@ ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar, } static int -ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, +ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif, struct ieee80211_chanctx_conf *ctx, bool restart) { @@ -7196,10 +7636,11 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, struct ath12k_base *ab = ar->ab; struct wmi_vdev_start_req_arg arg = {}; const struct cfg80211_chan_def *chandef = &ctx->def; - int he_support = arvif->vif->bss_conf.he_support; + struct ath12k_vif *ahvif = arvif->ahvif; + int he_support = ahvif->vif->bss_conf.he_support; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); reinit_completion(&ar->vdev_setup_done); @@ -7215,7 +7656,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode, chandef->chan->band, - arvif->vif->type); + ahvif->vif->type); arg.min_power = 0; arg.max_power = chandef->chan->max_power * 2; arg.max_reg_power = chandef->chan->max_reg_power * 2; @@ -7235,10 +7676,10 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, return ret; } - if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { - arg.ssid = arvif->u.ap.ssid; - arg.ssid_len = arvif->u.ap.ssid_len; - arg.hidden_ssid = arvif->u.ap.hidden_ssid; + if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = ahvif->u.ap.ssid; + arg.ssid_len = ahvif->u.ap.ssid_len; + arg.hidden_ssid = ahvif->u.ap.hidden_ssid; /* For now allow DFS for AP mode */ arg.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR); @@ -7285,7 +7726,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, ar->num_started_vdevs++; ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n", - arvif->vif->addr, arvif->vdev_id); + ahvif->vif->addr, arvif->vdev_id); /* Enable CAC Flag in the driver by checking the channel DFS cac time, * i.e dfs_cac_ms value which will be valid only for radar channels @@ -7294,7 +7735,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, * during CAC. */ /* TODO: Set the flag for other interface types as required */ - if (arvif->vdev_type == WMI_VDEV_TYPE_AP && + if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP && chandef->chan->dfs_cac_ms && chandef->chan->dfs_state == NL80211_DFS_USABLE) { set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); @@ -7311,13 +7752,13 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, return 0; } -static int ath12k_mac_vdev_start(struct ath12k_vif *arvif, +static int ath12k_mac_vdev_start(struct ath12k_link_vif *arvif, struct ieee80211_chanctx_conf *ctx) { return ath12k_mac_vdev_start_restart(arvif, ctx, false); } -static int ath12k_mac_vdev_restart(struct ath12k_vif *arvif, +static int ath12k_mac_vdev_restart(struct ath12k_link_vif *arvif, struct ieee80211_chanctx_conf *ctx) { return ath12k_mac_vdev_start_restart(arvif, ctx, true); @@ -7335,8 +7776,13 @@ static void ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ath12k_mac_change_chanctx_arg *arg = data; + struct ath12k_link_vif *arvif; + + lockdep_assert_wiphy(ahvif->ah->hw->wiphy); + + arvif = &ahvif->deflink; if (arvif->ar != arg->ar) return; @@ -7351,9 +7797,14 @@ static void ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ath12k_mac_change_chanctx_arg *arg = data; struct ieee80211_chanctx_conf *ctx; + struct ath12k_link_vif *arvif; + + lockdep_assert_wiphy(ahvif->ah->hw->wiphy); + + arvif = &ahvif->deflink; if (arvif->ar != arg->ar) return; @@ -7397,13 +7848,13 @@ static u32 ath12k_mac_nlwidth_to_wmiwidth(enum nl80211_chan_width width) } static int ath12k_mac_update_peer_puncturing_width(struct ath12k *ar, - struct ath12k_vif *arvif, + struct ath12k_link_vif *arvif, struct cfg80211_chan_def def) { u32 param_id, param_value; int ret; - if (arvif->vdev_type != WMI_VDEV_TYPE_STA) + if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA) return 0; param_id = WMI_PEER_CHWIDTH_PUNCTURE_20MHZ_BITMAP; @@ -7429,17 +7880,19 @@ ath12k_mac_update_vif_chan(struct ath12k *ar, { struct ath12k_wmi_vdev_up_params params = {}; struct ath12k_base *ab = ar->ab; + struct ath12k_link_vif *arvif; struct ieee80211_vif *vif; - struct ath12k_vif *arvif; + struct ath12k_vif *ahvif; int ret; int i; bool monitor_vif = false; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); for (i = 0; i < n_vifs; i++) { vif = vifs[i].vif; - arvif = ath12k_vif_to_arvif(vif); + ahvif = ath12k_vif_to_ahvif(vif); + arvif = &ahvif->deflink; if (vif->type == NL80211_IFTYPE_MONITOR) monitor_vif = true; @@ -7489,10 +7942,14 @@ ath12k_mac_update_vif_chan(struct ath12k *ar, memset(¶ms, 0, sizeof(params)); params.vdev_id = arvif->vdev_id; - params.aid = arvif->aid; + params.aid = ahvif->aid; params.bssid = arvif->bssid; if (vif->mbssid_tx_vif) { - params.tx_bssid = ath12k_vif_to_arvif(vif->mbssid_tx_vif)->bssid; + struct ath12k_vif *ahvif = + ath12k_vif_to_ahvif(vif->mbssid_tx_vif); + struct ath12k_link_vif *arvif = &ahvif->deflink; + + params.tx_bssid = arvif->bssid; params.nontx_profile_idx = vif->bss_conf.bssid_index; params.nontx_profile_cnt = 1 << vif->bss_conf.bssid_indicator; } @@ -7528,7 +7985,7 @@ ath12k_mac_update_active_vif_chan(struct ath12k *ar, struct ath12k_mac_change_chanctx_arg arg = { .ctx = ctx, .ar = ar }; struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_NORMAL, @@ -7558,14 +8015,14 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw, struct ath12k *ar; struct ath12k_base *ab; + lockdep_assert_wiphy(hw->wiphy); + ar = ath12k_get_ar_by_ctx(hw, ctx); if (!ar) return; ab = ar->ab; - mutex_lock(&ar->conf_mutex); - ath12k_dbg(ab, ATH12K_DBG_MAC, "mac chanctx change freq %u width %d ptr %p changed %x\n", ctx->def.chan->center_freq, ctx->def.width, ctx, changed); @@ -7574,7 +8031,7 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw, * switch_vif_chanctx(). */ if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) - goto unlock; + return; if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH || changed & IEEE80211_CHANCTX_CHANGE_RADAR || @@ -7582,16 +8039,14 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw, ath12k_mac_update_active_vif_chan(ar, ctx); /* TODO: Recalc radar detection */ - -unlock: - mutex_unlock(&ar->conf_mutex); } static int ath12k_start_vdev_delay(struct ath12k *ar, - struct ath12k_vif *arvif) + struct ath12k_link_vif *arvif) { struct ath12k_base *ab = ar->ab; - struct ieee80211_vif *vif = arvif->vif; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); int ret; if (WARN_ON(arvif->is_started)) @@ -7605,7 +8060,7 @@ static int ath12k_start_vdev_delay(struct ath12k *ar, return ret; } - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ret = ath12k_monitor_vdev_up(ar, arvif->vdev_id); if (ret) { ath12k_warn(ab, "failed put monitor up: %d\n", ret); @@ -7625,24 +8080,37 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { + struct ath12k_hw *ah = ath12k_hw_to_ah(hw); struct ath12k *ar; struct ath12k_base *ab; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + u8 link_id = link_conf->link_id; + struct ath12k_link_vif *arvif; int ret; + lockdep_assert_wiphy(hw->wiphy); + /* For multi radio wiphy, the vdev was not created during add_interface * create now since we have a channel ctx now to assign to a specific ar/fw */ - ar = ath12k_mac_assign_vif_to_vdev(hw, vif, ctx); - if (!ar) { + arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + if (!arvif) { WARN_ON(1); + return -ENOMEM; + } + + if (!arvif->is_started) { + ar = ath12k_mac_assign_vif_to_vdev(hw, arvif, ctx); + if (!ar) + return -EINVAL; + } else { + ath12k_warn(arvif->ar->ab, "failed to assign chanctx for vif %pM link id %u link vif is already started", + vif->addr, link_id); return -EINVAL; } ab = ar->ab; - mutex_lock(&ar->conf_mutex); - ath12k_dbg(ab, ATH12K_DBG_MAC, "mac chanctx assign ptr %p vdev_id %i\n", ctx, arvif->vdev_id); @@ -7651,8 +8119,8 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, /* for some targets bss peer must be created before vdev_start */ if (ab->hw_params->vdev_start_delay && - arvif->vdev_type != WMI_VDEV_TYPE_AP && - arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && + ahvif->vdev_type != WMI_VDEV_TYPE_AP && + ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && !ath12k_peer_exist_by_vdev_id(ab, arvif->vdev_id)) { memcpy(&arvif->chanctx, ctx, sizeof(*ctx)); ret = 0; @@ -7664,10 +8132,11 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, goto out; } - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ret = ath12k_mac_monitor_start(ar); if (ret) goto out; + arvif->is_started = true; goto out; } @@ -7680,7 +8149,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, goto out; } - if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created) + if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created) ath12k_mac_monitor_start(ar); arvif->is_started = true; @@ -7688,8 +8157,6 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, /* TODO: Setup ps and cts/rts protection */ out: - mutex_unlock(&ar->conf_mutex); - return ret; } @@ -7701,9 +8168,15 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, { struct ath12k *ar; struct ath12k_base *ab; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + u8 link_id = link_conf->link_id; int ret; + lockdep_assert_wiphy(hw->wiphy); + + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + /* The vif is expected to be attached to an ar's VDEV. * We leave the vif/vdev in this function as is * and not delete the vdev symmetric to assign_vif_chanctx() @@ -7711,32 +8184,28 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, * remove_interface() or when there is a change in channel * that moves the vif to a new ar */ - if (!arvif->is_created) + if (!arvif || !arvif->is_created) return; ar = arvif->ar; ab = ar->ab; - mutex_lock(&ar->conf_mutex); - ath12k_dbg(ab, ATH12K_DBG_MAC, "mac chanctx unassign ptr %p vdev_id %i\n", ctx, arvif->vdev_id); WARN_ON(!arvif->is_started); - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ret = ath12k_mac_monitor_stop(ar); - if (ret) { - mutex_unlock(&ar->conf_mutex); + if (ret) return; - } arvif->is_started = false; } - if (arvif->vdev_type != WMI_VDEV_TYPE_STA && - arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) { + if (ahvif->vdev_type != WMI_VDEV_TYPE_STA && + ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR) { ath12k_bss_disassoc(ar, arvif); ret = ath12k_mac_vdev_stop(arvif); if (ret) @@ -7745,11 +8214,12 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, } arvif->is_started = false; - if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && + if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->num_started_vdevs == 1 && ar->monitor_vdev_created) ath12k_mac_monitor_stop(ar); - mutex_unlock(&ar->conf_mutex); + ath12k_mac_remove_link_interface(hw, arvif); + ath12k_mac_unassign_link_vif(arvif); } static int @@ -7760,35 +8230,32 @@ ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, { struct ath12k *ar; + lockdep_assert_wiphy(hw->wiphy); + ar = ath12k_get_ar_by_ctx(hw, vifs->old_ctx); if (!ar) return -EINVAL; - mutex_lock(&ar->conf_mutex); - /* Switching channels across radio is not allowed */ - if (ar != ath12k_get_ar_by_ctx(hw, vifs->new_ctx)) { - mutex_unlock(&ar->conf_mutex); + if (ar != ath12k_get_ar_by_ctx(hw, vifs->new_ctx)) return -EINVAL; - } ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac chanctx switch n_vifs %d mode %d\n", n_vifs, mode); ath12k_mac_update_vif_chan(ar, vifs, n_vifs); - mutex_unlock(&ar->conf_mutex); - return 0; } static int ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value) { - struct ath12k_vif *arvif; + struct ath12k_link_vif *arvif; int ret = 0; - mutex_lock(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + list_for_each_entry(arvif, &ar->arvifs, list) { ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "setting mac vdev %d param %d value %d\n", param, arvif->vdev_id, value); @@ -7801,7 +8268,7 @@ ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value) break; } } - mutex_unlock(&ar->conf_mutex); + return ret; } @@ -7814,6 +8281,8 @@ static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) struct ath12k *ar; int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD, ret = 0, i; + lockdep_assert_wiphy(hw->wiphy); + /* Currently we set the rts threshold value to all the vifs across * all radios of the single wiphy. * TODO Once support for vif specific RTS threshold in mac80211 is @@ -7843,6 +8312,9 @@ static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) * supported. This effectively prevents mac80211 from doing frame * fragmentation in software. */ + + lockdep_assert_wiphy(hw->wiphy); + return -EOPNOTSUPP; } @@ -7887,6 +8359,8 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v struct ath12k *ar; int i; + lockdep_assert_wiphy(hw->wiphy); + if (drop) return; @@ -8020,14 +8494,14 @@ ath12k_mac_get_single_legacy_rate(struct ath12k *ar, return 0; } -static int ath12k_mac_set_fixed_rate_params(struct ath12k_vif *arvif, +static int ath12k_mac_set_fixed_rate_params(struct ath12k_link_vif *arvif, u32 rate, u8 nss, u8 sgi, u8 ldpc) { struct ath12k *ar = arvif->ar; u32 vdev_param; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n", arvif->vdev_id, rate, nss, sgi); @@ -8099,8 +8573,9 @@ ath12k_mac_vht_mcs_range_present(struct ath12k *ar, static void ath12k_mac_set_bitrate_mask_iter(void *data, struct ieee80211_sta *sta) { - struct ath12k_vif *arvif = data; - struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); + struct ath12k_link_vif *arvif = data; + struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta); + struct ath12k_link_sta *arsta = &ahsta->deflink; struct ath12k *ar = arvif->ar; if (arsta->arvif != arvif) @@ -8110,14 +8585,15 @@ static void ath12k_mac_set_bitrate_mask_iter(void *data, arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED; spin_unlock_bh(&ar->data_lock); - ieee80211_queue_work(ath12k_ar_to_hw(ar), &arsta->update_wk); + wiphy_work_queue(ath12k_ar_to_hw(ar)->wiphy, &arsta->update_wk); } static void ath12k_mac_disable_peer_fixed_rate(void *data, struct ieee80211_sta *sta) { - struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); - struct ath12k_vif *arvif = data; + struct ath12k_link_vif *arvif = data; + struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta); + struct ath12k_link_sta *arsta = &ahsta->deflink; struct ath12k *ar = arvif->ar; int ret; @@ -8139,9 +8615,10 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; struct cfg80211_chan_def def; - struct ath12k *ar = arvif->ar; + struct ath12k *ar; enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; @@ -8153,8 +8630,15 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, int ret; int num_rates; - if (ath12k_mac_vif_chan(vif, &def)) - return -EPERM; + lockdep_assert_wiphy(hw->wiphy); + + arvif = &ahvif->deflink; + + ar = arvif->ar; + if (ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)) { + ret = -EPERM; + goto out; + } band = def.chan->band; ht_mcs_mask = mask->control[band].ht_mcs; @@ -8183,9 +8667,9 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, arvif->vdev_id, ret); goto out; } - ieee80211_iterate_stations_atomic(hw, - ath12k_mac_disable_peer_fixed_rate, - arvif); + ieee80211_iterate_stations_mtx(hw, + ath12k_mac_disable_peer_fixed_rate, + arvif); } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask, &single_nss)) { rate = WMI_FIXED_RATE_NONE; @@ -8226,34 +8710,25 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, */ ath12k_warn(ar->ab, "Setting more than one MCS Value in bitrate mask not supported\n"); - ret = -EINVAL; - goto out; + return -EINVAL; } - ieee80211_iterate_stations_atomic(hw, - ath12k_mac_disable_peer_fixed_rate, - arvif); - - mutex_lock(&ar->conf_mutex); + ieee80211_iterate_stations_mtx(hw, + ath12k_mac_disable_peer_fixed_rate, + arvif); arvif->bitrate_mask = *mask; - ieee80211_iterate_stations_atomic(hw, - ath12k_mac_set_bitrate_mask_iter, - arvif); - - mutex_unlock(&ar->conf_mutex); + ieee80211_iterate_stations_mtx(hw, + ath12k_mac_set_bitrate_mask_iter, + arvif); } - mutex_lock(&ar->conf_mutex); - ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc); if (ret) { ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n", arvif->vdev_id, ret); } - mutex_unlock(&ar->conf_mutex); - out: return ret; } @@ -8265,9 +8740,12 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, struct ath12k_hw *ah = ath12k_hw_to_ah(hw); struct ath12k *ar; struct ath12k_base *ab; - struct ath12k_vif *arvif; + struct ath12k_vif *ahvif; + struct ath12k_link_vif *arvif; int recovery_count, i; + lockdep_assert_wiphy(hw->wiphy); + if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) return; @@ -8280,8 +8758,6 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, ieee80211_wake_queues(hw); for_each_ar(ah, ar, i) { - mutex_lock(&ar->conf_mutex); - ab = ar->ab; ath12k_warn(ar->ab, "pdev %d successfully recovered\n", @@ -8306,11 +8782,12 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, } list_for_each_entry(arvif, &ar->arvifs, list) { + ahvif = arvif->ahvif; ath12k_dbg(ab, ATH12K_DBG_BOOT, "reconfig cipher %d up %d vdev type %d\n", - arvif->key_cipher, + ahvif->key_cipher, arvif->is_up, - arvif->vdev_type); + ahvif->vdev_type); /* After trigger disconnect, then upper layer will * trigger connect again, then the PN number of @@ -8318,16 +8795,14 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, * side, hence PN number mismatch will not happen. */ if (arvif->is_up && - arvif->vdev_type == WMI_VDEV_TYPE_STA && - arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) { - ieee80211_hw_restart_disconnect(arvif->vif); + ahvif->vdev_type == WMI_VDEV_TYPE_STA && + ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) { + ieee80211_hw_restart_disconnect(ahvif->vif); ath12k_dbg(ab, ATH12K_DBG_BOOT, "restart disconnect\n"); } } - - mutex_unlock(&ar->conf_mutex); } } @@ -8338,7 +8813,7 @@ ath12k_mac_update_bss_chan_survey(struct ath12k *ar, int ret; enum wmi_bss_chan_info_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) || ar->rx_channel != channel) @@ -8370,6 +8845,8 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx, struct ieee80211_supported_band *sband; struct survey_info *ar_survey; + lockdep_assert_wiphy(hw->wiphy); + if (idx >= ATH12K_NUM_CHANS) return -ENOENT; @@ -8403,8 +8880,6 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx, ar_survey = &ar->survey[idx]; - mutex_lock(&ar->conf_mutex); - ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]); spin_lock_bh(&ar->data_lock); @@ -8416,7 +8891,6 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx, if (ar->rx_channel == survey->channel) survey->filled |= SURVEY_INFO_IN_USE; - mutex_unlock(&ar->conf_mutex); return 0; } @@ -8425,7 +8899,12 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct station_info *sinfo) { - struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); + struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta); + struct ath12k_link_sta *arsta; + + lockdep_assert_wiphy(hw->wiphy); + + arsta = &ahsta->deflink; sinfo->rx_duration = arsta->rx_duration; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION); @@ -8462,7 +8941,7 @@ static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw, ar = ath12k_ah_to_ar(ah, 0); - mutex_lock(&ar->conf_mutex); + lockdep_assert_wiphy(hw->wiphy); spin_lock_bh(&ar->data_lock); ar->scan.roc_notify = false; @@ -8470,8 +8949,6 @@ static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw, ath12k_scan_abort(ar); - mutex_unlock(&ar->conf_mutex); - cancel_delayed_work_sync(&ar->scan.timeout); return 0; @@ -8483,24 +8960,31 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw, int duration, enum ieee80211_roc_type type) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ath12k_hw *ah = ath12k_hw_to_ah(hw); struct ath12k_wmi_scan_req_arg arg; - struct ath12k *ar, *prev_ar; + struct ath12k_link_vif *arvif; + struct ath12k *ar; u32 scan_time_msec; bool create = true; + u8 link_id; int ret; - if (ah->num_radio == 1) { - WARN_ON(!arvif->is_created); - ar = ath12k_ah_to_ar(ah, 0); - goto scan; - } + lockdep_assert_wiphy(hw->wiphy); ar = ath12k_mac_select_scan_device(hw, vif, chan->center_freq); - if (!ar) - return -EINVAL; + if (!ar) { + ret = -EINVAL; + goto exit; + } + /* check if any of the links of ML VIF is already started on + * radio(ar) correpsondig to given scan frequency and use it, + * if not use deflink(link 0) for scan purpose. + */ + + link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar); + arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); /* If the vif is already assigned to a specific vdev of an ar, * check whether its already started, vdev which is started * are not allowed to switch to a new radio. @@ -8511,44 +8995,35 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw, * always on the same band for the vif */ if (arvif->is_created) { - if (WARN_ON(!arvif->ar)) - return -EINVAL; + if (WARN_ON(!arvif->ar)) { + ret = -EINVAL; + goto exit; + } - if (ar != arvif->ar && arvif->is_started) - return -EBUSY; + if (ar != arvif->ar && arvif->is_started) { + ret = -EBUSY; + goto exit; + } if (ar != arvif->ar) { - /* backup the previously used ar ptr, since the vdev delete - * would assign the arvif->ar to NULL after the call - */ - prev_ar = arvif->ar; - mutex_lock(&prev_ar->conf_mutex); - ret = ath12k_mac_vdev_delete(prev_ar, vif); - mutex_unlock(&prev_ar->conf_mutex); - if (ret) { - ath12k_warn(prev_ar->ab, - "unable to delete scan vdev for roc: %d\n", - ret); - return ret; - } + ath12k_mac_remove_link_interface(hw, arvif); + ath12k_mac_unassign_link_vif(arvif); } else { create = false; } } if (create) { - mutex_lock(&ar->conf_mutex); - ret = ath12k_mac_vdev_create(ar, vif); - mutex_unlock(&ar->conf_mutex); + arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + + ret = ath12k_mac_vdev_create(ar, arvif); if (ret) { ath12k_warn(ar->ab, "unable to create scan vdev for roc: %d\n", ret); - return -EINVAL; + goto exit; } } -scan: - mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); switch (ar->scan.state) { @@ -8623,9 +9098,8 @@ scan: free_chan_list: kfree(arg.chan_list); -exit: - mutex_unlock(&ar->conf_mutex); +exit: return ret; } @@ -8633,16 +9107,20 @@ static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *data) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct ath12k_rekey_data *rekey_data = &arvif->rekey_data; + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_rekey_data *rekey_data; struct ath12k_hw *ah = ath12k_hw_to_ah(hw); struct ath12k *ar = ath12k_ah_to_ar(ah, 0); + struct ath12k_link_vif *arvif; + + lockdep_assert_wiphy(hw->wiphy); + + arvif = &ahvif->deflink; + rekey_data = &arvif->rekey_data; ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set rekey data vdev %d\n", arvif->vdev_id); - mutex_lock(&ar->conf_mutex); - memcpy(rekey_data->kck, data->kck, NL80211_KCK_LEN); memcpy(rekey_data->kek, data->kek, NL80211_KEK_LEN); @@ -8659,8 +9137,6 @@ static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw, rekey_data->kck, NL80211_KEK_LEN); ath12k_dbg_dump(ar->ab, ATH12K_DBG_MAC, "replay ctr", NULL, &rekey_data->replay_ctr, sizeof(rekey_data->replay_ctr)); - - mutex_unlock(&ar->conf_mutex); } static const struct ieee80211_ops ath12k_ops = { @@ -8673,7 +9149,9 @@ static const struct ieee80211_ops ath12k_ops = { .remove_interface = ath12k_mac_op_remove_interface, .update_vif_offload = ath12k_mac_op_update_vif_offload, .config = ath12k_mac_op_config, - .bss_info_changed = ath12k_mac_op_bss_info_changed, + .link_info_changed = ath12k_mac_op_link_info_changed, + .vif_cfg_changed = ath12k_mac_op_vif_cfg_changed, + .change_vif_links = ath12k_mac_op_change_vif_links, .configure_filter = ath12k_mac_op_configure_filter, .hw_scan = ath12k_mac_op_hw_scan, .cancel_hw_scan = ath12k_mac_op_cancel_hw_scan, @@ -8681,7 +9159,7 @@ static const struct ieee80211_ops ath12k_ops = { .set_rekey_data = ath12k_mac_op_set_rekey_data, .sta_state = ath12k_mac_op_sta_state, .sta_set_txpwr = ath12k_mac_op_sta_set_txpwr, - .sta_rc_update = ath12k_mac_op_sta_rc_update, + .link_sta_rc_update = ath12k_mac_op_sta_rc_update, .conf_tx = ath12k_mac_op_conf_tx, .set_antenna = ath12k_mac_op_set_antenna, .get_antenna = ath12k_mac_op_get_antenna, @@ -9320,7 +9798,7 @@ static void ath12k_mac_setup(struct ath12k *ar) spin_lock_init(&ar->data_lock); INIT_LIST_HEAD(&ar->arvifs); INIT_LIST_HEAD(&ar->ppdu_stats_info); - mutex_init(&ar->conf_mutex); + init_completion(&ar->vdev_setup_done); init_completion(&ar->vdev_delete_done); init_completion(&ar->peer_assoc_done); @@ -9501,7 +9979,7 @@ err: return ret; } -int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif, +int ath12k_mac_vif_set_keepalive(struct ath12k_link_vif *arvif, enum wmi_sta_keepalive_method method, u32 interval) { @@ -9509,9 +9987,9 @@ int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif, struct ath12k *ar = arvif->ar; int ret; - lockdep_assert_held(&ar->conf_mutex); + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - if (arvif->vdev_type != WMI_VDEV_TYPE_STA) + if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA) return 0; if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map)) |