diff options
| author | Sriram R <quic_srirrama@quicinc.com> | 2024-10-15 20:14:06 +0300 |
|---|---|---|
| committer | Jeff Johnson <quic_jjohnson@quicinc.com> | 2024-10-16 18:36:19 +0300 |
| commit | 3dd2c68f206ef7020d12b9f85cbfe05ca8662cf4 (patch) | |
| tree | a025df3d174bd8da0e56d5bcec14267d28c3a093 /drivers/net/wireless/ath/ath12k/mac.c | |
| parent | 25ff1ae52139b53c1a69f55ce235077528245b55 (diff) | |
| download | linux-3dd2c68f206ef7020d12b9f85cbfe05ca8662cf4.tar.xz | |
wifi: ath12k: prepare vif data structure for MLO handling
To prepare the driver for MLO support, split the driver vif data structure to
scale for multiple links. This requires changing the use of arvif to per link
and not per hw which can now comprise of multiple links. Also since most
configurations from mac80211 are done per link, do refactoring of the driver
functions to apply these configurations at link level.
Split ath12k_vif which is the driver private of ieee80211_vif to store link
specific information as ath12k_link_vif. For default use cases the ath12k vif
will have a preallocated link vif called deflink which will be used by non ML
and the first link vif of ML vif.
With MLO support to be added, remaining link vifs will be allocated during
channel assignment where vdev create/start happens. These link vifs will be
freed during interface down.
Current ath12k_vif(arvif) structure
+---------------+ +---------------+ +---------------+
| ieee80211_vif | | ieee80211_vif | | ieee80211_vif |
| private data | | private data | | private data |
| | | | | |
| ath12k_vif | | ath12k_vif | | ath12k_vif |
| (arvif) | | (arvif) | | (arvif) |
| | | | | |
| +----------+ | | +----------+ | | +----------+ |
| |*ar (2GHz)| | | |*ar (5GHz)| | | |*ar (2GHz)| |
| +----------+ | | +----------+ | | +----------+ |
| | | | | |
+---------------+ +---------------+ +---------------+
The new ath12k_vif (ahvif) containing ath12k_link_vif(s) (arvif) (deflink is
preallocated member which is always the first link if ieee80211_vif is MLD and
is the only link otherwise):
+---------------------------------+
| ieee80211_vif |
| private data |
| |
| ath12k_vif(ahvif) |
| |
| +-------------------------------+
| |ath12k_link_vif deflink (arvif)|
| | +---------------+ |
| | | *ar(2GHz) | |
| +-------------------------------+
| +-------------------------------+
| | ath12k_link_vif *link (arvif)|
| | +---------------+ |
| | | *ar(5GHz) | |
| +-------------------------------+
| +-------------------------------+
| | ath12k_link_vif *link (arvif)|
| | +---------------+ |
| | | *ar(6GHz) | |
| +-------------------------------+
| |
+---------------------------------+
To refactor existing ath12k_vif to make use of link vifs, following
changes are made:
1. ath12k_vif now called by variable name ahvif storing multiple
arvifs (struct ah12k_link_vif) and also has a back pointer to ieee80211_vif.
2. In this patch set, only deflink is used to be on par with the
existing code. When MLO support is added the link id will be used to fetch
the arvif.
3. For mac80211 ops which doesn't use specific link_id, the config or info
is common for the vif, hence apply the config to all link vifs.
The links_map in the ahvif, will be used to identify all the link vifs that
are setup.
4. Change ath12k_vif_to_arvif() as ath12k_vif_to_ahvif() to fetch the
hw level vif. The link vif can be fetched from ahvif->link[], or the
deflink can be accessed via ahvif->deflink. API to access link
vif (arvif) by passing link_id can be introduced with MLO Support.
5. The ieee80211_vif can be accessed from ahvif using ath12k_ahvif_to_vif().
The locking continues to use wiphy_lock() for protecting access to most data in
struct ath12k&co, there are no changes in that regard. Though struct
ath12k_vif::link[] is protected with RCU.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Co-developed-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://patch.msgid.link/20241015171416.518022-2-kvalo@kernel.org
Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath12k/mac.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/mac.c | 726 |
1 files changed, 470 insertions, 256 deletions
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index d3c37b895b69..92f05bc7c7fa 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -250,7 +250,7 @@ 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); @@ -539,18 +539,22 @@ 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); + struct ath12k_link_vif *arvif = &ahvif->deflink; if (arvif->vdev_id == arvif_iter->vdev_id && arvif->ar == arvif_iter->ar) arvif_iter->arvif = arvif; } -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 +571,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 +662,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,9 +678,9 @@ 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); @@ -706,11 +711,11 @@ 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; @@ -731,7 +736,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) @@ -771,7 +776,7 @@ 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; @@ -825,7 +830,7 @@ 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; @@ -864,7 +869,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; @@ -1230,8 +1235,9 @@ 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; @@ -1257,7 +1263,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); @@ -1324,7 +1330,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; @@ -1381,7 +1387,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; @@ -1473,19 +1479,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"); @@ -1523,22 +1532,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; @@ -1546,7 +1558,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"); @@ -1557,14 +1569,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", @@ -1598,10 +1610,11 @@ 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; @@ -1625,15 +1638,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; } @@ -1654,7 +1671,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; @@ -1677,7 +1695,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); @@ -1708,9 +1727,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; @@ -1723,12 +1742,14 @@ static void ath12k_peer_assoc_h_basic(struct ath12k *ar, struct ieee80211_sta *sta, struct ath12k_wmi_peer_assoc_arg *arg) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); + struct ath12k_link_vif *arvif; u32 aid; lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; if (vif->type == NL80211_IFTYPE_STATION) aid = vif->cfg.aid; else @@ -1749,16 +1770,18 @@ static void ath12k_peer_assoc_h_crypto(struct ath12k *ar, struct ieee80211_sta *sta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ieee80211_bss_conf *info = &vif->bss_conf; + struct ath12k_link_vif *arvif; 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_wiphy(hw->wiphy); + arvif = &ahvif->deflink; if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return; @@ -1811,12 +1834,13 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar, struct ieee80211_sta *sta, struct ath12k_wmi_peer_assoc_arg *arg) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates; struct cfg80211_chan_def def; const struct ieee80211_supported_band *sband; const struct ieee80211_rate *rates; struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); + struct ath12k_link_vif *arvif; enum nl80211_band band; u32 ratemask; u8 rate; @@ -1824,6 +1848,7 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar, lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return; @@ -1874,8 +1899,9 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar, struct ieee80211_sta *sta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_link_vif *arvif; struct cfg80211_chan_def def; enum nl80211_band band; const u8 *ht_mcs_mask; @@ -1885,6 +1911,7 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar, lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + arvif = &ahvif->deflink; if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return; @@ -2035,8 +2062,9 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, struct ieee80211_sta *sta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_link_vif *arvif; struct cfg80211_chan_def def; enum nl80211_band band; const u16 *vht_mcs_mask; @@ -2045,6 +2073,10 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, u8 max_nss, vht_mcs; int i; + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + arvif = &ahvif->deflink; + if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return; @@ -2383,9 +2415,9 @@ static void ath12k_peer_assoc_h_qos(struct ath12k *ar, struct ieee80211_sta *sta, struct ath12k_wmi_peer_assoc_arg *arg) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); - switch (arvif->vdev_type) { + switch (ahvif->vdev_type) { case WMI_VDEV_TYPE_AP: if (sta->wme) { /* TODO: Check WME vs QoS */ @@ -2415,7 +2447,7 @@ 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 ath12k_link_vif *arvif, struct ieee80211_sta *sta) { struct ath12k_wmi_ap_ps_arg arg; @@ -2581,13 +2613,17 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, struct ieee80211_sta *sta, 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; + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + arvif = &ahvif->deflink; if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return; @@ -2726,13 +2762,17 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar, struct ieee80211_sta *sta, struct ath12k_wmi_peer_assoc_arg *arg) { + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); 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); + struct ath12k_link_vif *arvif; u32 *rx_mcs, *tx_mcs; + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + arvif = &ahvif->deflink; if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht) return; @@ -2832,7 +2872,7 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar, /* 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) @@ -2852,10 +2892,11 @@ 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 ieee80211_sta *ap_sta; @@ -2866,7 +2907,7 @@ static void ath12k_bss_assoc(struct ath12k *ar, 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(); @@ -2906,11 +2947,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) { @@ -2952,7 +2993,7 @@ 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; @@ -3002,9 +3043,10 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar, struct ieee80211_vif *vif, struct cfg80211_chan_def *def) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); const struct ieee80211_supported_band *sband; + struct ath12k_link_vif *arvif; u8 basic_rate_idx; int hw_rate_code; u32 vdev_param; @@ -3013,6 +3055,7 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar, lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; sband = hw->wiphy->bands[def->chan->band]; basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; bitrate = sband->bitrates[basic_rate_idx].bitrate; @@ -3036,9 +3079,10 @@ 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_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; @@ -3049,7 +3093,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); @@ -3057,8 +3101,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); @@ -3083,10 +3126,10 @@ 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_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; @@ -3099,7 +3142,7 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif) 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; @@ -3131,11 +3174,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; @@ -3205,10 +3249,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)) @@ -3319,7 +3363,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_chan(vif, &def)) { band = def.chan->band; mcast_rate = vif->bss_conf.mcast_rate[band]; @@ -3363,7 +3407,7 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, } if (changed & BSS_CHANGED_BASIC_RATES && - !ath12k_mac_vif_chan(arvif->vif, &def)) + !ath12k_mac_vif_chan(vif, &def)) ath12k_recalculate_mgmt_rate(ar, vif, &def); if (changed & BSS_CHANGED_TWT) { @@ -3409,12 +3453,12 @@ 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_arvif_get_cache(struct ath12k_link_vif *arvif) { if (!arvif->cache) arvif->cache = kzalloc(sizeof(*arvif->cache), GFP_KERNEL); @@ -3422,7 +3466,7 @@ static struct ath12k_vif_cache *ath12k_arvif_get_cache(struct ath12k_vif *arvif) return arvif->cache; } -static void ath12k_arvif_put_cache(struct ath12k_vif *arvif) +static void ath12k_arvif_put_cache(struct ath12k_link_vif *arvif) { kfree(arvif->cache); arvif->cache = NULL; @@ -3434,11 +3478,16 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, 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; lockdep_assert_wiphy(hw->wiphy); + /* TODO use info->link_id and fetch corresponding ahvif->link[] + * with MLO support. + */ + arvif = &ahvif->deflink; ar = ath12k_get_ar_by_vif(hw, vif); /* if the vdev is not created on a certain radio, @@ -3446,10 +3495,16 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, */ if (!ar) { + /* TODO Once link vif is fetched based on link id from + * info, avoid using the deflink above and cache the link + * configs in ahvif per link. + */ cache = ath12k_arvif_get_cache(arvif); if (!cache) return; + arvif->cache->bss_conf_changed |= changed; + return; } @@ -3662,7 +3717,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, { 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_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; int ret; @@ -3671,6 +3727,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; + if (ah->num_radio == 1) { WARN_ON(!arvif->is_created); ar = ath12k_ah_to_ar(ah, 0); @@ -3808,11 +3866,14 @@ exit: 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; @@ -3823,7 +3884,7 @@ static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw, 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) @@ -3838,6 +3899,8 @@ 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_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -3890,13 +3953,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; @@ -3942,8 +4005,9 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ath12k_base *ab = ar->ab; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_link_vif *arvif; struct ath12k_peer *peer; struct ath12k_sta *arsta; const u8 *peer_addr; @@ -3952,12 +4016,13 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + arvif = &ahvif->deflink; 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; @@ -4051,19 +4116,23 @@ 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_vif_cache *cache; struct ath12k *ar; int ret; lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; + /* 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; @@ -4079,13 +4148,21 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 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; } + /* Note: Currently only deflink of ahvif is used here, once MLO + * support is added the allocated links (i.e ahvif->links[]) + * should be use based on link id passed from mac80211 and such link + * access needs to be protected with ah->conf_mutex. + */ ret = ath12k_mac_set_key(ar, cmd, vif, sta, key); + return ret; } @@ -4104,7 +4181,7 @@ ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar, } static int -ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif, +ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif, struct ieee80211_sta *sta, const struct cfg80211_bitrate_mask *mask, enum nl80211_band band) @@ -4154,16 +4231,18 @@ static int ath12k_station_assoc(struct ath12k *ar, struct ieee80211_sta *sta, bool reassoc) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ath12k_wmi_peer_assoc_arg peer_arg; int ret; struct cfg80211_chan_def def; enum nl80211_band band; + struct ath12k_link_vif *arvif; struct cfg80211_bitrate_mask *mask; u8 num_vht_rates; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + arvif = &ahvif->deflink; if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return -EPERM; @@ -4242,11 +4321,13 @@ static int ath12k_station_disassoc(struct ath12k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - 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; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + arvif = &ahvif->deflink; if (!sta->wme) { arvif->num_legacy_stations--; ret = ath12k_recalc_rtscts_prot(arvif); @@ -4266,8 +4347,8 @@ static int ath12k_station_disassoc(struct ath12k *ar, 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; @@ -4278,15 +4359,17 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk) const struct cfg80211_bitrate_mask *mask; struct ath12k_wmi_peer_assoc_arg peer_arg; enum wmi_phy_mode peer_phymode; + struct ieee80211_vif *vif; lockdep_assert_wiphy(wiphy); arsta = container_of(wk, struct ath12k_sta, update_wk); sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); 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_chan(vif, &def))) return; band = def.chan->band; @@ -4310,7 +4393,7 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk) 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, vif, sta, &peer_arg); peer_phymode = peer_arg.peer_phymode; if (bw > bw_prev) { @@ -4405,7 +4488,7 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk) * 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, vif, sta, &peer_arg, true); err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg); @@ -4420,14 +4503,14 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk) } } -static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif, +static int ath12k_mac_inc_num_stations(struct ath12k_link_vif *arvif, struct ieee80211_sta *sta) { struct ath12k *ar = arvif->ar; 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) @@ -4438,14 +4521,14 @@ static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif, return 0; } -static void ath12k_mac_dec_num_stations(struct ath12k_vif *arvif, +static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif, struct ieee80211_sta *sta) { struct ath12k *ar = arvif->ar; 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--; @@ -4456,20 +4539,21 @@ static int ath12k_mac_station_add(struct ath12k *ar, struct ieee80211_sta *sta) { struct ath12k_base *ab = ar->ab; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); struct ath12k_wmi_peer_create_arg peer_param; + struct ath12k_link_vif *arvif; int ret; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + arvif = &ahvif->deflink; ret = ath12k_mac_inc_num_stations(arvif, sta); 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; @@ -4510,7 +4594,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); @@ -4565,14 +4649,17 @@ 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 *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_peer *peer; int ret = 0; lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; + ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { WARN_ON_ONCE(1); @@ -4593,7 +4680,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, new_state == IEEE80211_STA_NOTEXIST)) { wiphy_work_cancel(hw->wiphy, &arsta->update_wk); - if (arvif->vdev_type == WMI_VDEV_TYPE_STA) { + if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) { ath12k_bss_disassoc(ar, arvif); ret = ath12k_mac_vdev_stop(arvif); if (ret) @@ -4689,22 +4776,29 @@ 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); @@ -4713,9 +4807,10 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw, if (ret) { ath12k_warn(ar->ab, "failed to set tx power for station ret: %d\n", ret); - return ret; + goto out; } +out: return ret; } @@ -4726,9 +4821,14 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, { struct ath12k *ar; struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); - 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_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) { @@ -4736,11 +4836,20 @@ 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; + } 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; @@ -4793,16 +4902,19 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, spin_unlock_bh(&ar->data_lock); 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) { @@ -4825,19 +4937,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; @@ -4852,7 +4964,7 @@ exit: return ret; } -static int ath12k_mac_conf_tx(struct ath12k_vif *arvif, +static int ath12k_mac_conf_tx(struct ath12k_link_vif *arvif, unsigned int link_id, u16 ac, const struct ieee80211_tx_queue_params *params) { @@ -4910,22 +5022,26 @@ 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_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + struct ath12k_vif_cache *cache; struct ath12k *ar; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct ath12k_vif_cache *cache = arvif->cache; int ret; lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; 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); if (!cache) return -ENOSPC; + cache->tx_conf.changed = true; cache->tx_conf.ac = ac; cache->tx_conf.tx_queue_params = *params; + return 0; } @@ -5000,10 +5116,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; @@ -5031,7 +5148,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; } @@ -5039,7 +5156,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; } @@ -5700,7 +5817,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; @@ -5768,7 +5885,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; @@ -5780,8 +5898,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) { @@ -5836,18 +5954,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); } @@ -5859,7 +5977,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; @@ -6188,7 +6307,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; @@ -6210,19 +6329,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; @@ -6234,22 +6356,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; @@ -6316,14 +6439,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) { @@ -6346,9 +6470,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; @@ -6361,14 +6486,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); @@ -6395,21 +6520,22 @@ 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); lockdep_assert_wiphy(hw->wiphy); - ath12k_mac_update_vif_offload(arvif); + 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 ieee80211_vif *vif) { 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 = ath12k_vif_to_ahvif(vif); struct ath12k_wmi_vdev_create_arg vdev_arg = {0}; struct ath12k_wmi_peer_create_arg peer_param; + struct ath12k_link_vif *arvif; u32 param_id, param_value; u16 nss; int i; @@ -6417,37 +6543,38 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; 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); @@ -6455,7 +6582,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); @@ -6498,7 +6625,7 @@ 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; @@ -6574,15 +6701,21 @@ 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; + /* TODO use appropriate link id once MLO support is added. + */ + arvif->link_id = ATH12K_DEFAULT_LINK_ID; + rcu_assign_pointer(ahvif->link[arvif->link_id], arvif); + ahvif->links_map = BIT(arvif->link_id); + synchronize_rcu(); + 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, @@ -6618,16 +6751,18 @@ err: return ret; } -static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif) +static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif) { - 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_vif_cache *cache; struct ath12k_base *ab = ar->ab; - + struct ath12k_link_vif *arvif; int ret; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + arvif = &ahvif->deflink; + cache = arvif->cache; if (!cache) return; @@ -6659,7 +6794,8 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx) { - 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_hw *ah = hw->priv; struct ath12k *ar, *prev_ar; struct ath12k_base *ab; @@ -6667,6 +6803,8 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw, lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; + if (ah->num_radio == 1) ar = ah->radio; else if (ctx) @@ -6742,14 +6880,19 @@ unlock: 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; lockdep_assert_wiphy(hw->wiphy); - memset(arvif, 0, sizeof(*arvif)); + memset(ahvif, 0, sizeof(*ahvif)); - arvif->vif = vif; + ahvif->ah = ah; + ahvif->vif = vif; + arvif = &ahvif->deflink; + arvif->ahvif = ahvif; INIT_LIST_HEAD(&arvif->list); INIT_DELAYED_WORK(&arvif->connection_loss_work, @@ -6776,6 +6919,7 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw, * vdev needs to be created */ ath12k_mac_assign_vif_to_vdev(hw, vif, NULL); + return 0; } @@ -6806,12 +6950,15 @@ 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) { - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); struct ath12k_base *ab = ar->ab; + struct ath12k_link_vif *arvif; unsigned long time_left; int ret; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + arvif = &ahvif->deflink; reinit_completion(&ar->vdev_delete_done); ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id); @@ -6832,7 +6979,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) { @@ -6862,6 +7009,12 @@ err_vdev_del: /* TODO: recal traffic pause state based on the available vdevs */ arvif->is_created = false; arvif->ar = NULL; + if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS) { + rcu_assign_pointer(ahvif->link[arvif->link_id], NULL); + synchronize_rcu(); + ahvif->links_map &= ~(BIT(arvif->link_id)); + arvif->link_id = ATH12K_INVALID_LINK_ID; + } return ret; } @@ -6869,13 +7022,16 @@ 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_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; struct ath12k_base *ab; struct ath12k *ar; int ret; lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; + if (!arvif->is_created) { /* if we cached some config but never received assign chanctx, * free the allocated cache. @@ -6892,7 +7048,7 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw, ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n", arvif->vdev_id); - if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + if (ahvif->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", @@ -6989,7 +7145,7 @@ 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; @@ -7025,7 +7181,8 @@ 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); @@ -7035,6 +7192,7 @@ static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw, return -EINVAL; ar = ath12k_ah_to_ar(ah, 0); + arvif = &ahvif->deflink; ret = ath12k_mac_ampdu_action(arvif, params); if (ret) @@ -7162,7 +7320,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) { @@ -7170,7 +7328,8 @@ 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_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -7189,7 +7348,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; @@ -7209,10 +7368,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); @@ -7259,7 +7418,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 @@ -7268,7 +7427,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); @@ -7285,13 +7444,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); @@ -7309,8 +7468,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; @@ -7325,9 +7489,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; @@ -7371,13 +7540,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; @@ -7403,8 +7572,9 @@ 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; @@ -7413,7 +7583,8 @@ ath12k_mac_update_vif_chan(struct ath12k *ar, 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; @@ -7463,10 +7634,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; } @@ -7559,10 +7734,11 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw, } 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)) @@ -7576,7 +7752,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); @@ -7598,7 +7774,8 @@ ath12k_mac_op_assign_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; int ret; lockdep_assert_wiphy(hw->wiphy); @@ -7606,10 +7783,12 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, /* 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 */ + arvif = &ahvif->deflink; + ar = ath12k_mac_assign_vif_to_vdev(hw, vif, ctx); - if (!ar) { - WARN_ON(1); - return -EINVAL; + if (WARN_ON(!ar)) { + ret = -EINVAL; + goto out; } ab = ar->ab; @@ -7622,22 +7801,26 @@ 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)); - return 0; + ret = 0; + goto out; } - if (WARN_ON(arvif->is_started)) - return -EBUSY; + if (WARN_ON(arvif->is_started)) { + ret = -EBUSY; + 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) - return ret; + goto out; + arvif->is_started = true; - return ret; + goto out; } ret = ath12k_mac_vdev_start(arvif, ctx); @@ -7645,16 +7828,17 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n", arvif->vdev_id, vif->addr, ctx->def.chan->center_freq, ret); - return ret; + 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; /* TODO: Setup ps and cts/rts protection */ +out: return ret; } @@ -7666,11 +7850,14 @@ 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; int ret; lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; + /* 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() @@ -7690,7 +7877,7 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, 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) return; @@ -7698,8 +7885,8 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, 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) @@ -7708,7 +7895,7 @@ 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); } @@ -7742,7 +7929,7 @@ ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, 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; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -7985,7 +8172,7 @@ 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; @@ -8064,7 +8251,7 @@ 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_link_vif *arvif = data; struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); struct ath12k *ar = arvif->ar; @@ -8081,8 +8268,8 @@ static void ath12k_mac_set_bitrate_mask_iter(void *data, static void ath12k_mac_disable_peer_fixed_rate(void *data, struct ieee80211_sta *sta) { + struct ath12k_link_vif *arvif = data; struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); - struct ath12k_vif *arvif = data; struct ath12k *ar = arvif->ar; int ret; @@ -8104,9 +8291,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; @@ -8120,8 +8308,13 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, lockdep_assert_wiphy(hw->wiphy); - if (ath12k_mac_vif_chan(vif, &def)) - return -EPERM; + arvif = &ahvif->deflink; + + ar = arvif->ar; + if (ath12k_mac_vif_chan(vif, &def)) { + ret = -EPERM; + goto out; + } band = def.chan->band; ht_mcs_mask = mask->control[band].ht_mcs; @@ -8129,8 +8322,10 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); sgi = mask->control[band].gi; - if (sgi == NL80211_TXRATE_FORCE_LGI) - return -EINVAL; + if (sgi == NL80211_TXRATE_FORCE_LGI) { + ret = -EINVAL; + goto out; + } /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it * requires passing at least one of used basic rates along with them. @@ -8146,7 +8341,7 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, if (ret) { ath12k_warn(ar->ab, "failed to get single legacy rate for vdev %i: %d\n", arvif->vdev_id, ret); - return ret; + goto out; } ieee80211_iterate_stations_mtx(hw, ath12k_mac_disable_peer_fixed_rate, @@ -8210,6 +8405,7 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, arvif->vdev_id, ret); } +out: return ret; } @@ -8220,7 +8416,8 @@ 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); @@ -8261,11 +8458,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 @@ -8273,9 +8471,9 @@ 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"); @@ -8435,9 +8633,10 @@ 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_link_vif *arvif; struct ath12k *ar, *prev_ar; u32 scan_time_msec; bool create = true; @@ -8445,6 +8644,8 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw, lockdep_assert_wiphy(hw->wiphy); + arvif = &ahvif->deflink; + if (ah->num_radio == 1) { WARN_ON(!arvif->is_created); ar = ath12k_ah_to_ar(ah, 0); @@ -8452,8 +8653,10 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw, } ar = ath12k_mac_select_scan_device(hw, vif, chan->center_freq); - if (!ar) - return -EINVAL; + if (!ar) { + ret = -EINVAL; + goto exit; + } /* If the vif is already assigned to a specific vdev of an ar, * check whether its already started, vdev which is started @@ -8465,11 +8668,15 @@ 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 @@ -8481,7 +8688,7 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw, ath12k_warn(prev_ar->ab, "unable to delete scan vdev for roc: %d\n", ret); - return ret; + goto exit; } } else { create = false; @@ -8493,7 +8700,7 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw, if (ret) { ath12k_warn(ar->ab, "unable to create scan vdev for roc: %d\n", ret); - return -EINVAL; + goto exit; } } @@ -8522,7 +8729,7 @@ scan: spin_unlock_bh(&ar->data_lock); if (ret) - return ret; + goto exit; scan_time_msec = hw->wiphy->max_remain_on_channel_duration * 2; @@ -8531,8 +8738,10 @@ scan: arg.num_chan = 1; arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list), GFP_KERNEL); - if (!arg.chan_list) - return -ENOMEM; + if (!arg.chan_list) { + ret = -ENOMEM; + goto exit; + } arg.vdev_id = arvif->vdev_id; arg.scan_id = ATH12K_SCAN_ID; @@ -8571,6 +8780,7 @@ scan: free_chan_list: kfree(arg.chan_list); +exit: return ret; } @@ -8578,13 +8788,17 @@ 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); @@ -9444,7 +9658,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) { @@ -9454,7 +9668,7 @@ int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif, 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)) |
