[PATCH v4 1/3] wifi: ath12k: prepare vif data structure for MLO handling
Baochen Qiang
quic_bqiang at quicinc.com
Tue Jun 18 00:47:46 PDT 2024
On 6/17/2024 9:16 PM, Rameshkumar Sundaram wrote:
> From: Sriram R <quic_srirrama at quicinc.com>
>
> 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)| |
> | +----------+ | | +----------+ | | +----------+ |
> | | | | | |
> +---------------+ +---------------+ +---------------+
>
> Proposed 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 stores multiple
> arvifs(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_vif_to_vif()
>
> Locking:
> Currently modifications to members of arvif and arsta are protected by ar->conf_mutex
> and it stays as such.
> Now with these hw level structure (ahvif) being introduced, any modifications
> to its members and link objects (i.e., arvifs[] which are dynamically allocated)
> needs to be protected for writing and ah->conf_mutex is used for the same.
> Also, atomic contexts(say WMI events and certain mac_ops) that we currently have in driver
> will not(shouldn't be allowed) do any modifications but can read them and
> rcu_read_lock() is used for the same.
>
> 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 at quicinc.com>
> Co-developed-by: Rameshkumar Sundaram <quic_ramess at quicinc.com>
> Signed-off-by: Rameshkumar Sundaram <quic_ramess at quicinc.com>
> ---
> drivers/net/wireless/ath/ath12k/core.h | 69 ++-
> drivers/net/wireless/ath/ath12k/dp.c | 21 +-
> drivers/net/wireless/ath/ath12k/dp.h | 3 +-
> drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +-
> drivers/net/wireless/ath/ath12k/dp_rx.h | 2 +-
> drivers/net/wireless/ath/ath12k/dp_tx.c | 9 +-
> drivers/net/wireless/ath/ath12k/dp_tx.h | 2 +-
> drivers/net/wireless/ath/ath12k/mac.c | 733 ++++++++++++++++--------
> drivers/net/wireless/ath/ath12k/mac.h | 9 +-
> drivers/net/wireless/ath/ath12k/p2p.c | 17 +-
> drivers/net/wireless/ath/ath12k/p2p.h | 2 +-
> drivers/net/wireless/ath/ath12k/peer.c | 7 +-
> drivers/net/wireless/ath/ath12k/peer.h | 4 +-
> drivers/net/wireless/ath/ath12k/wmi.c | 12 +-
> 14 files changed, 592 insertions(+), 300 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
> index b483899ca136..d47b6413aaad 100644
> --- a/drivers/net/wireless/ath/ath12k/core.h
> +++ b/drivers/net/wireless/ath/ath12k/core.h
> @@ -229,10 +229,8 @@ struct ath12k_vif_cache {
> u32 bss_conf_changed;
> };
>
> -struct ath12k_vif {
> +struct ath12k_link_vif {
> u32 vdev_id;
> - enum wmi_vdev_type vdev_type;
> - enum wmi_vdev_subtype vdev_subtype;
> u32 beacon_interval;
> u32 dtim_period;
> u16 ast_hash;
> @@ -242,13 +240,38 @@ struct ath12k_vif {
> u8 search_type;
>
> struct ath12k *ar;
> - struct ieee80211_vif *vif;
>
> int bank_id;
> u8 vdev_id_check_en;
>
> struct wmi_wmm_params_all_arg wmm_params;
> struct list_head list;
> +
> + bool is_created;
> + bool is_started;
> + bool is_up;
> + u8 bssid[ETH_ALEN];
> + struct cfg80211_bitrate_mask bitrate_mask;
> + struct delayed_work connection_loss_work;
> + int num_legacy_stations;
> + int rtscts_prot_mode;
> + int txpower;
> + bool rsnie_present;
> + bool wpaie_present;
> + struct ieee80211_chanctx_conf chanctx;
> + u8 vdev_stats_id;
> + u32 punct_bitmap;
> + u8 link_id;
> + struct ath12k_vif *ahvif;
> + struct ath12k_vif_cache *cache;
> +};
> +
> +struct ath12k_vif {
> + enum wmi_vdev_type vdev_type;
> + enum wmi_vdev_subtype vdev_subtype;
> + struct ieee80211_vif *vif;
> + struct ath12k_hw *ah;
> +
> union {
> struct {
> u32 uapsd;
> @@ -266,31 +289,21 @@ struct ath12k_vif {
> } ap;
> } u;
>
> - bool is_created;
> - bool is_started;
> - bool is_up;
> u32 aid;
> - u8 bssid[ETH_ALEN];
> - struct cfg80211_bitrate_mask bitrate_mask;
> - struct delayed_work connection_loss_work;
> - int num_legacy_stations;
> - int rtscts_prot_mode;
> - int txpower;
> - bool rsnie_present;
> - bool wpaie_present;
> - struct ieee80211_chanctx_conf chanctx;
> u32 key_cipher;
> u8 tx_encap_type;
> - u8 vdev_stats_id;
> - u32 punct_bitmap;
> bool ps;
> - struct ath12k_vif_cache *cache;
> +
> + struct ath12k_link_vif deflink;
> + struct ath12k_link_vif __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
> + /* indicates bitmap of link vif created in FW */
> + u16 links_map;
> };
>
> struct ath12k_vif_iter {
> u32 vdev_id;
> struct ath12k *ar;
> - struct ath12k_vif *arvif;
> + struct ath12k_link_vif *arvif;
> };
>
> #define HAL_AST_IDX_INVALID 0xFFFF
> @@ -426,7 +439,7 @@ struct ath12k_wbm_tx_stats {
> };
>
> struct ath12k_sta {
> - struct ath12k_vif *arvif;
> + struct ath12k_link_vif *arvif;
>
> /* the following are protected by ar->data_lock */
> u32 changed; /* IEEE80211_RC_* */
> @@ -543,7 +556,7 @@ struct ath12k {
> */
> struct mutex conf_mutex;
> /* protects the radio specific data like debug stats, ppdu_stats_info stats,
> - * vdev_stop_status info, scan data, ath12k_sta info, ath12k_vif info,
> + * vdev_stop_status info, scan data, ath12k_sta info, ath12k_link_vif info,
> * channel context data, survey info, test mode data.
> */
> spinlock_t data_lock;
> @@ -639,6 +652,11 @@ struct ath12k_hw {
> enum ath12k_hw_state state;
> bool regd_updated;
> bool use_6ghz_regd;
> +
> + /* To synchronize concurrent access of ahvif->link[]
> + * between mac80211 operations.
> + */
> + struct mutex conf_mutex;
> u8 num_radio;
>
> /* Keep last */
> @@ -995,7 +1013,7 @@ static inline struct ath12k_skb_rxcb *ATH12K_SKB_RXCB(struct sk_buff *skb)
> return (struct ath12k_skb_rxcb *)skb->cb;
> }
>
> -static inline struct ath12k_vif *ath12k_vif_to_arvif(struct ieee80211_vif *vif)
> +static inline struct ath12k_vif *ath12k_vif_to_ahvif(struct ieee80211_vif *vif)
> {
> return (struct ath12k_vif *)vif->drv_priv;
> }
> @@ -1005,6 +1023,11 @@ static inline struct ath12k_sta *ath12k_sta_to_arsta(struct ieee80211_sta *sta)
> return (struct ath12k_sta *)sta->drv_priv;
> }
>
> +static inline struct ieee80211_vif *ath12k_vif_to_vif(struct ath12k_vif *ahvif)
better naming as ath12k_ahvif_to_vif()?
> +{
> + return container_of((void *)ahvif, struct ieee80211_vif, drv_priv);
> +}
> +
> static inline struct ath12k *ath12k_ab_to_ar(struct ath12k_base *ab,
> int mac_id)
> {
> diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
> index 61aa78d8bd8c..30aac0dd5a80 100644
> --- a/drivers/net/wireless/ath/ath12k/dp.c
> +++ b/drivers/net/wireless/ath/ath12k/dp.c
> @@ -327,20 +327,22 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring,
> }
>
> static
> -u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif *arvif)
> +u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab,
> + struct ath12k_link_vif *arvif)
> {
> u32 bank_config = 0;
> + struct ath12k_vif *ahvif = arvif->ahvif;
>
> /* Only valid for raw frames with HW crypto enabled.
> * With SW crypto, mac80211 sets key per packet
> */
> - if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
> + if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
> test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags))
> bank_config |=
> - u32_encode_bits(ath12k_dp_tx_get_encrypt_type(arvif->key_cipher),
> + u32_encode_bits(ath12k_dp_tx_get_encrypt_type(ahvif->key_cipher),
> HAL_TX_BANK_CONFIG_ENCRYPT_TYPE);
>
> - bank_config |= u32_encode_bits(arvif->tx_encap_type,
> + bank_config |= u32_encode_bits(ahvif->tx_encap_type,
> HAL_TX_BANK_CONFIG_ENCAP_TYPE);
> bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_SRC_BUFFER_SWAP) |
> u32_encode_bits(0, HAL_TX_BANK_CONFIG_LINK_META_SWAP) |
> @@ -355,7 +357,7 @@ u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif
> HAL_TX_ADDRY_EN),
> HAL_TX_BANK_CONFIG_ADDRY_EN);
>
> - bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(arvif->vif) ? 3 : 0,
> + bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(ahvif->vif) ? 3 : 0,
> HAL_TX_BANK_CONFIG_MESH_EN) |
> u32_encode_bits(arvif->vdev_id_check_en,
> HAL_TX_BANK_CONFIG_VDEV_ID_CHECK_EN);
> @@ -365,7 +367,8 @@ u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif
> return bank_config;
> }
>
> -static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab, struct ath12k_vif *arvif,
> +static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab,
> + struct ath12k_link_vif *arvif,
> struct ath12k_dp *dp)
> {
> int bank_id = DP_INVALID_BANK_ID;
> @@ -1099,9 +1102,9 @@ int ath12k_dp_htt_connect(struct ath12k_dp *dp)
> return 0;
> }
>
> -static void ath12k_dp_update_vdev_search(struct ath12k_vif *arvif)
> +static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif)
> {
> - switch (arvif->vdev_type) {
> + switch (arvif->ahvif->vdev_type) {
> case WMI_VDEV_TYPE_STA:
> /* TODO: Verify the search type and flags since ast hash
> * is not part of peer mapv3
> @@ -1120,7 +1123,7 @@ static void ath12k_dp_update_vdev_search(struct ath12k_vif *arvif)
> }
> }
>
> -void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif)
> +void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif)
> {
> struct ath12k_base *ab = ar->ab;
>
> diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
> index 742094545089..4161486e98ab 100644
> --- a/drivers/net/wireless/ath/ath12k/dp.h
> +++ b/drivers/net/wireless/ath/ath12k/dp.h
> @@ -16,6 +16,7 @@ struct ath12k_base;
> struct ath12k_peer;
> struct ath12k_dp;
> struct ath12k_vif;
> +struct ath12k_link_vif;
> struct hal_tcl_status_ring;
> struct ath12k_ext_irq_grp;
>
> @@ -1810,7 +1811,7 @@ int ath12k_dp_service_srng(struct ath12k_base *ab,
> struct ath12k_ext_irq_grp *irq_grp,
> int budget);
> int ath12k_dp_htt_connect(struct ath12k_dp *dp);
> -void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif);
> +void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif);
> void ath12k_dp_free(struct ath12k_base *ab);
> int ath12k_dp_alloc(struct ath12k_base *ab);
> void ath12k_dp_cc_config(struct ath12k_base *ab);
> diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
> index 54aea3c22311..781cb7af8cf0 100644
> --- a/drivers/net/wireless/ath/ath12k/dp_rx.c
> +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
> @@ -1090,7 +1090,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
> return ret;
> }
>
> -int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_vif *arvif,
> +int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
> const u8 *peer_addr,
> enum set_key_cmd key_cmd,
> struct ieee80211_key_conf *key)
> diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
> index 2ff421160181..8c1bccc4f0f0 100644
> --- a/drivers/net/wireless/ath/ath12k/dp_rx.h
> +++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
> @@ -88,7 +88,7 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
> struct ieee80211_ampdu_params *params);
> int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
> struct ieee80211_ampdu_params *params);
> -int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_vif *arvif,
> +int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
> const u8 *peer_addr,
> enum set_key_cmd key_cmd,
> struct ieee80211_key_conf *key);
> diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c
> index c4cfa7cf7cb9..fb5de5c2794d 100644
> --- a/drivers/net/wireless/ath/ath12k/dp_tx.c
> +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c
> @@ -10,7 +10,7 @@
> #include "hw.h"
>
> static enum hal_tcl_encap_type
> -ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb)
> +ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb)
> {
> struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
> struct ath12k_base *ab = arvif->ar->ab;
> @@ -162,7 +162,7 @@ static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb)
> return 0;
> }
>
> -int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
> +int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
> struct sk_buff *skb)
> {
> struct ath12k_base *ab = ar->ab;
> @@ -176,6 +176,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
> struct sk_buff *skb_ext_desc;
> struct hal_srng *tcl_ring;
> struct ieee80211_hdr *hdr = (void *)skb->data;
> + struct ath12k_vif *ahvif = arvif->ahvif;
> struct dp_tx_ring *tx_ring;
> u8 pool_id;
> u8 hal_ring_id;
> @@ -219,7 +220,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
> ti.bank_id = arvif->bank_id;
> ti.meta_data_flags = arvif->tcl_metadata;
>
> - if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
> + if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
> test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) {
> if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) {
> ti.encrypt_type =
> @@ -304,7 +305,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
> ti.desc_id = tx_desc->desc_id;
> ti.data_len = skb->len;
> skb_cb->paddr = ti.paddr;
> - skb_cb->vif = arvif->vif;
> + skb_cb->vif = ahvif->vif;
> skb_cb->ar = ar;
>
> if (msdu_ext_desc) {
> diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.h b/drivers/net/wireless/ath/ath12k/dp_tx.h
> index 55ff8cc721e3..46dce23501f3 100644
> --- a/drivers/net/wireless/ath/ath12k/dp_tx.h
> +++ b/drivers/net/wireless/ath/ath12k/dp_tx.h
> @@ -16,7 +16,7 @@ struct ath12k_dp_htt_wbm_tx_status {
> };
>
> int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab);
> -int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
> +int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
> struct sk_buff *skb);
> void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id);
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 2259ce22cc8b..8bd8efcc1264 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -247,7 +247,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);
> @@ -536,18 +536,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());
why rcu lock needed here? what needs protecting?
> arvif_iter.vdev_id = vdev_id;
> arvif_iter.ar = ar;
>
> @@ -564,12 +568,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]);
> @@ -655,7 +659,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
> @@ -691,7 +696,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;
>
> @@ -745,7 +750,7 @@ static int ath12k_mac_txpower_recalc(struct ath12k *ar)
> 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;
> @@ -784,7 +789,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;
> @@ -1147,8 +1152,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;
>
> @@ -1174,7 +1180,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);
> @@ -1242,7 +1248,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;
> @@ -1299,7 +1305,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;
> @@ -1391,19 +1397,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");
> @@ -1441,22 +1450,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_vif_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;
>
> @@ -1464,7 +1476,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");
> @@ -1475,14 +1487,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",
> @@ -1516,10 +1528,11 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
> 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;
>
> @@ -1543,15 +1556,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;
> }
> @@ -1572,7 +1589,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;
> @@ -1595,7 +1613,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);
>
> @@ -1626,9 +1645,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;
> @@ -1641,12 +1660,15 @@ 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_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + arvif = &ahvif->deflink;
> if (vif->type == NL80211_IFTYPE_STATION)
> aid = vif->cfg.aid;
> else
> @@ -1667,16 +1689,19 @@ 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_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + arvif = &ahvif->deflink;
> if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
> return;
>
> @@ -1729,19 +1754,22 @@ 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;
> int i;
>
> + lockdep_assert_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + arvif = &ahvif->deflink;
> if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
> return;
>
> @@ -1792,8 +1820,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;
> @@ -1801,8 +1830,10 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
> u8 max_nss;
> u32 stbc;
>
> + lockdep_assert_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + arvif = &ahvif->deflink;
> if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
> return;
>
> @@ -1953,8 +1984,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;
> @@ -1963,6 +1995,9 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
> u8 max_nss, vht_mcs;
> int i;
>
> + lockdep_assert_held(&ahvif->ah->conf_mutex);
> + arvif = &ahvif->deflink;
> +
> if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
> return;
>
> @@ -2300,9 +2335,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 */
> @@ -2332,7 +2367,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;
> @@ -2498,13 +2533,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_held(&ahvif->ah->conf_mutex);
> +
> + arvif = &ahvif->deflink;
> if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
> return;
>
> @@ -2643,13 +2682,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_held(&ahvif->ah->conf_mutex);
> +
> + arvif = &ahvif->deflink;
> if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
> return;
>
> @@ -2749,7 +2792,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)
> @@ -2766,10 +2809,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_vif_to_vif(ahvif);
> struct ath12k_wmi_vdev_up_params params = {};
> struct ath12k_wmi_peer_assoc_arg peer_arg;
> struct ieee80211_sta *ap_sta;
> @@ -2780,7 +2824,7 @@ static void ath12k_bss_assoc(struct ath12k *ar,
> lockdep_assert_held(&ar->conf_mutex);
>
> 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();
>
> @@ -2820,11 +2864,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) {
> @@ -2865,7 +2909,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;
>
> @@ -2913,17 +2957,20 @@ 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;
> u16 bitrate;
> int ret;
>
> + lockdep_assert_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + 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;
> @@ -2947,9 +2994,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_vif_to_vif(arvif->ahvif);
> struct ath12k *ar = arvif->ar;
> struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
> struct sk_buff *tmpl;
> @@ -2960,7 +3008,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);
> @@ -2968,8 +3016,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);
> @@ -2994,10 +3041,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;
> @@ -3010,7 +3057,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;
> @@ -3042,11 +3089,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_vif_to_vif(ahvif);
> struct ieee80211_vif_cfg *vif_cfg = &vif->cfg;
> struct cfg80211_chan_def def;
> u32 param_id, param_value;
> @@ -3116,10 +3164,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))
> @@ -3230,7 +3278,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];
>
> @@ -3274,7 +3322,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) {
> @@ -3320,12 +3368,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);
> @@ -3333,7 +3381,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;
> @@ -3344,10 +3392,17 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
> struct ieee80211_bss_conf *info,
> u64 changed)
> {
> + 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_vif_cache *cache;
> + struct ath12k_link_vif *arvif;
>
> + mutex_lock(&ah->conf_mutex);
> + /* 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,
> @@ -3355,10 +3410,17 @@ 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)
> + if (!cache) {
> + mutex_unlock(&ah->conf_mutex);
> return;
> + }
> arvif->cache->bss_conf_changed |= changed;
> + mutex_unlock(&ah->conf_mutex);
> return;
> }
>
> @@ -3367,6 +3429,7 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
> ath12k_mac_bss_info_changed(ar, arvif, info, changed);
>
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
> }
>
> static struct ath12k*
> @@ -3575,13 +3638,17 @@ 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 = {};
> int ret;
> int i;
> bool create = true;
>
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> +
> if (ah->num_radio == 1) {
> WARN_ON(!arvif->is_created);
> ar = ath12k_ah_to_ar(ah, 0);
> @@ -3592,9 +3659,10 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
> * requested in the hw_req, select the corresponding radio
> */
> ar = ath12k_mac_select_scan_device(hw, vif, hw_req->req.channels[0]->center_freq);
> - if (!ar)
> + if (!ar) {
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> -
> + }
> /* 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.
> @@ -3605,11 +3673,15 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
> * always on the same band for the vif
> */
> if (arvif->is_created) {
> - if (WARN_ON(!arvif->ar))
> + if (WARN_ON(!arvif->ar)) {
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> + }
>
> - if (ar != arvif->ar && arvif->is_started)
> + if (ar != arvif->ar && arvif->is_started) {
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> + }
>
> if (ar != arvif->ar) {
> /* backup the previously used ar ptr, since the vdev delete
> @@ -3632,6 +3704,7 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
> mutex_unlock(&ar->conf_mutex);
> if (ret) {
> ath12k_warn(ar->ab, "unable to create scan vdev %d\n", ret);
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> }
> }
> @@ -3714,21 +3787,30 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
> kfree(arg.extraie.ptr);
>
> mutex_unlock(&ar->conf_mutex);
> -
> + mutex_unlock(&ah->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_hw *ah = ath12k_hw_to_ah(hw);
> + struct ath12k_link_vif *arvif;
> struct ath12k *ar;
>
> - if (!arvif->is_created)
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> +
> + if (!arvif->is_created) {
> + mutex_unlock(&ah->conf_mutex);
> return;
> + }
>
> ar = arvif->ar;
>
> + mutex_unlock(&ah->conf_mutex);
> +
> mutex_lock(&ar->conf_mutex);
> ath12k_scan_abort(ar);
> mutex_unlock(&ar->conf_mutex);
> @@ -3736,7 +3818,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)
> @@ -3751,6 +3833,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_vif_to_vif(ahvif);
>
> lockdep_assert_held(&arvif->ar->conf_mutex);
>
> @@ -3803,13 +3887,13 @@ static int ath12k_install_key(struct ath12k_vif *arvif,
> 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;
> @@ -3855,22 +3939,25 @@ 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;
> int ret = 0;
> u32 flags = 0;
>
> + lockdep_assert_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + 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;
> @@ -3966,41 +4053,60 @@ 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_hw *ah = ath12k_hw_to_ah(hw);
> + struct ath12k_link_vif *arvif;
> struct ath12k_vif_cache *cache;
> struct ath12k *ar;
> int ret;
>
> + mutex_lock(&ah->conf_mutex);
> + 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) {
> + mutex_unlock(&ah->conf_mutex);
> return 1;
> + }
>
> - if (key->keyidx > WMI_MAX_KEY_INDEX)
> + if (key->keyidx > WMI_MAX_KEY_INDEX) {
> + mutex_unlock(&ah->conf_mutex);
> 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);
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> }
>
> cache = ath12k_arvif_get_cache(arvif);
> - if (!cache)
> + if (!cache) {
> + mutex_unlock(&ah->conf_mutex);
> return -ENOSPC;
> + }
> cache->key_conf.cmd = cmd;
> cache->key_conf.key = key;
> cache->key_conf.changed = true;
> + mutex_unlock(&ah->conf_mutex);
> 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.
> + */
> +
> mutex_lock(&ar->conf_mutex);
> ret = ath12k_mac_set_key(ar, cmd, vif, sta, key);
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
> return ret;
> }
>
> @@ -4019,7 +4125,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)
> @@ -4069,16 +4175,19 @@ 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_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + arvif = &ahvif->deflink;
> if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
> return -EPERM;
>
> @@ -4152,11 +4261,14 @@ 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_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + arvif = &ahvif->deflink;
> if (!sta->wme) {
> arvif->num_legacy_stations--;
> ret = ath12k_recalc_rtscts_prot(arvif);
> @@ -4176,8 +4288,8 @@ static int ath12k_station_disassoc(struct ath12k *ar,
> static void ath12k_sta_rc_update_wk(struct work_struct *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;
> @@ -4188,13 +4300,15 @@ 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 ieee80211_vif *vif;
>
> arsta = container_of(wk, struct ath12k_sta, update_wk);
> sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
> arvif = arsta->arvif;
> + vif = ath12k_vif_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;
> @@ -4220,7 +4334,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *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) {
> @@ -4315,7 +4429,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *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);
> @@ -4332,14 +4446,14 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
> mutex_unlock(&ar->conf_mutex);
> }
>
> -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_held(&ar->conf_mutex);
>
> - 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)
> @@ -4350,14 +4464,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_held(&ar->conf_mutex);
>
> - 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--;
> @@ -4368,20 +4482,22 @@ 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_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + 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;
> @@ -4422,7 +4538,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);
> @@ -4477,12 +4593,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_hw *ah = ath12k_hw_to_ah(hw);
> + 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;
>
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> +
> /* cancel must be done outside the mutex to avoid deadlock */
> if ((old_state == IEEE80211_STA_NONE &&
> new_state == IEEE80211_STA_NOTEXIST))
> @@ -4491,9 +4612,9 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
> ar = ath12k_get_ar_by_vif(hw, vif);
> if (!ar) {
> WARN_ON_ONCE(1);
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> }
> -
> mutex_lock(&ar->conf_mutex);
>
> if (old_state == IEEE80211_STA_NOTEXIST &&
> @@ -4508,7 +4629,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
> 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) {
> + if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
> ath12k_bss_disassoc(ar, arvif);
> ret = ath12k_mac_vdev_stop(arvif);
> if (ret)
> @@ -4596,6 +4717,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
> }
>
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
>
> return ret;
> }
> @@ -4606,20 +4728,28 @@ 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;
>
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> +
> if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
> txpwr = 0;
> } else {
> txpwr = sta->deflink.txpwr.power;
> - if (!txpwr)
> + if (!txpwr) {
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> + }
> }
>
> - if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL)
> + if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL) {
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> + }
>
> ar = ath12k_ah_to_ar(ah, 0);
>
> @@ -4635,6 +4765,7 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
>
> out:
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
> return ret;
> }
>
> @@ -4645,7 +4776,8 @@ 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;
>
> @@ -4655,11 +4787,14 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
> return;
> }
>
> + rcu_read_lock();
> + arvif = &ahvif->deflink;
does ath12k_vif::deflink need rcu protect? note it is not declared as rcu*, and even mac80211 uses it without holding such lock. See
ieee80211_mgd_auth() {
struct ieee80211_link_data *link;
...
if()
...
else
link = &sdata->deflink;
...
}
> 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;
> @@ -4712,16 +4847,18 @@ 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);
> + 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) {
> @@ -4744,19 +4881,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;
> @@ -4771,7 +4908,7 @@ static int ath12k_conf_tx_uapsd(struct ath12k_vif *arvif,
> 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)
> {
> @@ -4829,27 +4966,34 @@ 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_hw *ah = ath12k_hw_to_ah(hw);
> + 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;
>
> + mutex_lock(&ah->conf_mutex);
> + 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)
> + if (!cache) {
> + mutex_unlock(&ah->conf_mutex);
> return -ENOSPC;
> + }
> cache->tx_conf.changed = true;
> cache->tx_conf.ac = ac;
> cache->tx_conf.tx_queue_params = *params;
> + mutex_unlock(&ah->conf_mutex);
> return 0;
> }
>
> mutex_lock(&ar->conf_mutex);
> ret = ath12k_mac_conf_tx(arvif, link_id, ac, params);
> mutex_unlock(&ar->conf_mutex);
> -
> + mutex_unlock(&ah->conf_mutex);
> return ret;
> }
>
> @@ -4919,10 +5063,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;
> @@ -4950,7 +5095,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;
> }
>
> @@ -4958,7 +5103,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;
> }
>
> @@ -5619,7 +5764,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;
> @@ -5687,7 +5832,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;
>
> @@ -5699,8 +5845,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) {
> @@ -5755,18 +5901,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);
> }
> @@ -5778,7 +5924,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;
> @@ -6131,7 +6278,7 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw)
> }
>
> 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;
> @@ -6153,19 +6300,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;
>
> @@ -6177,22 +6327,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;
> @@ -6259,14 +6410,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) {
> @@ -6289,9 +6441,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_vif_to_vif(ahvif);
> struct ath12k *ar = arvif->ar;
> struct ath12k_base *ab = ar->ab;
> u32 param_id, param_value;
> @@ -6304,14 +6457,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);
> @@ -6338,57 +6491,60 @@ 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);
>
> - 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;
> int ret, vdev_id;
>
> + lockdep_assert_held(&ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + 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);
> @@ -6396,7 +6552,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);
> @@ -6439,7 +6595,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;
> @@ -6515,15 +6671,19 @@ 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);
> 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,
> @@ -6559,16 +6719,19 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
> 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_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
>
> + arvif = &ahvif->deflink;
> + cache = arvif->cache;
> if (!cache)
> return;
>
> @@ -6600,12 +6763,16 @@ 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;
> int ret;
>
> + lockdep_assert_held(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> +
> if (ah->num_radio == 1)
> ar = ah->radio;
> else if (ctx)
> @@ -6687,12 +6854,18 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
> 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));
> + mutex_lock(&ah->conf_mutex);
> + 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,
> @@ -6719,6 +6892,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);
> + mutex_unlock(&ah->conf_mutex);
> return 0;
> }
>
> @@ -6749,12 +6923,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)
> {
> - 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_held(&ahvif->ah->conf_mutex);
> lockdep_assert_held(&ar->conf_mutex);
> +
> + arvif = &ahvif->deflink;
> reinit_completion(&ar->vdev_delete_done);
>
> ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
> @@ -6775,7 +6953,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) {
> @@ -6805,6 +6983,12 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif)
> /* 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;
> }
> @@ -6812,16 +6996,21 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif)
> 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_hw *ah = ath12k_hw_to_ah(hw);
> + struct ath12k_link_vif *arvif;
> struct ath12k_base *ab;
> struct ath12k *ar;
> int ret;
>
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> if (!arvif->is_created) {
> /* if we cached some config but never received assign chanctx,
> * free the allocated cache.
> */
> ath12k_arvif_put_cache(arvif);
> + mutex_unlock(&ah->conf_mutex);
> return;
> }
>
> @@ -6835,7 +7024,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",
> @@ -6845,6 +7034,7 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
> ath12k_mac_vdev_delete(ar, vif);
>
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
> }
>
> /* FIXME: Has to be verified. */
> @@ -6936,7 +7126,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;
> @@ -6972,7 +7162,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;
>
> ar = ath12k_get_ar_by_vif(hw, vif);
> @@ -6980,10 +7171,13 @@ static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
> return -EINVAL;
>
> ar = ath12k_ah_to_ar(ah, 0);
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
>
> mutex_lock(&ar->conf_mutex);
> ret = ath12k_mac_ampdu_action(arvif, params);
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
>
> if (ret)
> ath12k_warn(ar->ab, "pdev idx %d unable to perform ampdu action %d ret %d\n",
> @@ -7114,7 +7308,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)
> {
> @@ -7122,7 +7316,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_held(&ar->conf_mutex);
> @@ -7141,7 +7336,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;
> @@ -7161,10 +7356,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);
> @@ -7211,7 +7406,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
> @@ -7220,7 +7415,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);
> @@ -7237,13 +7432,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);
> @@ -7261,8 +7456,12 @@ 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_held(&ahvif->ah->conf_mutex);
> + arvif = &ahvif->deflink;
>
> if (arvif->ar != arg->ar)
> return;
> @@ -7277,9 +7476,13 @@ 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_held(&ahvif->ah->conf_mutex);
> + arvif = &ahvif->deflink;
>
> if (arvif->ar != arg->ar)
> return;
> @@ -7323,13 +7526,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;
> @@ -7355,8 +7558,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;
> @@ -7365,7 +7569,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;
> @@ -7415,10 +7620,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;
> }
> @@ -7481,12 +7690,16 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
> struct ieee80211_chanctx_conf *ctx,
> u32 changed)
> {
> + struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
> struct ath12k *ar;
> struct ath12k_base *ab;
>
> + mutex_lock(&ah->conf_mutex);
> ar = ath12k_get_ar_by_ctx(hw, ctx);
> - if (!ar)
> + if (!ar) {
> + mutex_unlock(&ah->conf_mutex);
> return;
> + }
>
> ab = ar->ab;
>
> @@ -7511,13 +7724,15 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
>
> unlock:
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->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_vif_to_vif(arvif->ahvif);
> int ret;
>
> if (WARN_ON(arvif->is_started))
> @@ -7531,7 +7746,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);
> @@ -7551,17 +7766,22 @@ 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);
> + struct ath12k_link_vif *arvif;
> int ret;
>
> /* 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
> */
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> ar = ath12k_mac_assign_vif_to_vdev(hw, vif, ctx);
> if (!ar) {
> WARN_ON(1);
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> }
>
> @@ -7577,8 +7797,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;
> @@ -7590,7 +7810,7 @@ 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;
> @@ -7606,7 +7826,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;
> @@ -7615,6 +7835,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
>
> out:
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
>
> return ret;
> }
> @@ -7625,11 +7846,15 @@ ath12k_mac_op_unassign_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);
> + struct ath12k_link_vif *arvif;
> int ret;
>
> + mutex_lock(&ah->conf_mutex);
> + 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()
> @@ -7637,8 +7862,10 @@ 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->is_created) {
> + mutex_unlock(&ah->conf_mutex);
> return;
> + }
>
> ar = arvif->ar;
> ab = ar->ab;
> @@ -7651,18 +7878,19 @@ 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) {
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
> 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)
> @@ -7671,11 +7899,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);
> + mutex_unlock(&ah->conf_mutex);
> }
>
> static int
> @@ -7684,17 +7913,19 @@ ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
> int n_vifs,
> enum ieee80211_chanctx_switch_mode mode)
> {
> + struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
> struct ath12k *ar;
>
> ar = ath12k_get_ar_by_ctx(hw, vifs->old_ctx);
> if (!ar)
> return -EINVAL;
> -
> + mutex_lock(&ah->conf_mutex);
> 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);
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> }
>
> @@ -7702,8 +7933,8 @@ ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
> "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);
> + mutex_unlock(&ah->conf_mutex);
>
> return 0;
> }
> @@ -7711,7 +7942,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;
>
> mutex_lock(&ar->conf_mutex);
> @@ -7946,7 +8177,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;
> @@ -8025,7 +8256,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;
>
> @@ -8042,8 +8273,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;
>
> @@ -8065,9 +8296,11 @@ 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_hw *ah = ath12k_hw_to_ah(hw);
> + 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;
> @@ -8079,8 +8312,13 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
> int ret;
> int num_rates;
>
> - if (ath12k_mac_vif_chan(vif, &def))
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> + ar = arvif->ar;
> + if (ath12k_mac_vif_chan(vif, &def)) {
> + mutex_unlock(&ah->conf_mutex);
> return -EPERM;
> + }
>
> band = def.chan->band;
> ht_mcs_mask = mask->control[band].ht_mcs;
> @@ -8181,6 +8419,7 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
> mutex_unlock(&ar->conf_mutex);
>
> out:
> + mutex_unlock(&ah->conf_mutex);
> return ret;
> }
>
> @@ -8191,7 +8430,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;
>
> if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
> @@ -8232,11 +8472,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
> @@ -8244,9 +8485,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");
> @@ -8413,14 +8654,18 @@ 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;
> int ret;
>
> + mutex_lock(&ah->conf_mutex);
> + arvif = &ahvif->deflink;
> +
> if (ah->num_radio == 1) {
> WARN_ON(!arvif->is_created);
> ar = ath12k_ah_to_ar(ah, 0);
> @@ -8428,8 +8673,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)
> + if (!ar) {
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> + }
>
> /* If the vif is already assigned to a specific vdev of an ar,
> * check whether its already started, vdev which is started
> @@ -8441,11 +8688,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))
> + if (WARN_ON(!arvif->ar)) {
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> + }
>
> - if (ar != arvif->ar && arvif->is_started)
> + if (ar != arvif->ar && arvif->is_started) {
> + mutex_unlock(&ah->conf_mutex);
> return -EBUSY;
> + }
>
> if (ar != arvif->ar) {
> /* backup the previously used ar ptr, since the vdev delete
> @@ -8459,6 +8710,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);
> + mutex_unlock(&ah->conf_mutex);
> return ret;
> }
> } else {
> @@ -8473,6 +8725,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);
> + mutex_unlock(&ah->conf_mutex);
> return -EINVAL;
> }
> }
> @@ -8555,6 +8808,7 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
> kfree(arg.chan_list);
> exit:
> mutex_unlock(&ar->conf_mutex);
> + mutex_unlock(&ah->conf_mutex);
>
> return ret;
> }
> @@ -9281,6 +9535,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab,
> ah->num_radio = num_pdev_map;
>
> mutex_init(&ah->hw_mutex);
> + mutex_init(&ah->conf_mutex);
>
> for (i = 0; i < num_pdev_map; i++) {
> ab = pdev_map[i].ab;
> diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
> index 69fd282b9dd3..ef54349cb159 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.h
> +++ b/drivers/net/wireless/ath/ath12k/mac.h
> @@ -40,6 +40,9 @@ struct ath12k_generic_iter {
> #define ATH12K_TX_POWER_MAX_VAL 70
> #define ATH12K_TX_POWER_MIN_VAL 0
>
> +#define ATH12K_DEFAULT_LINK_ID 0
> +#define ATH12K_INVALID_LINK_ID 255
> +
> enum ath12k_supported_bw {
> ATH12K_BW_20 = 0,
> ATH12K_BW_40 = 1,
> @@ -64,9 +67,9 @@ u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
> void __ath12k_mac_scan_finish(struct ath12k *ar);
> void ath12k_mac_scan_finish(struct ath12k *ar);
>
> -struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id);
> -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(struct ath12k *ar, u32 vdev_id);
> +struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
> + u32 vdev_id);
> struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id);
> struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id);
>
> diff --git a/drivers/net/wireless/ath/ath12k/p2p.c b/drivers/net/wireless/ath/ath12k/p2p.c
> index 3a851ee15b2f..84cccf7d91e7 100644
> --- a/drivers/net/wireless/ath/ath12k/p2p.c
> +++ b/drivers/net/wireless/ath/ath12k/p2p.c
> @@ -69,20 +69,20 @@ static size_t ath12k_p2p_noa_ie_len_compute(const struct ath12k_wmi_p2p_noa_info
> return len;
> }
>
> -static void ath12k_p2p_noa_ie_assign(struct ath12k_vif *arvif, void *ie,
> +static void ath12k_p2p_noa_ie_assign(struct ath12k_link_vif *arvif, void *ie,
> size_t len)
> {
> struct ath12k *ar = arvif->ar;
>
> lockdep_assert_held(&ar->data_lock);
>
> - kfree(arvif->u.ap.noa_data);
> + kfree(arvif->ahvif->u.ap.noa_data);
>
> - arvif->u.ap.noa_data = ie;
> - arvif->u.ap.noa_len = len;
> + arvif->ahvif->u.ap.noa_data = ie;
> + arvif->ahvif->u.ap.noa_len = len;
> }
>
> -static void __ath12k_p2p_noa_update(struct ath12k_vif *arvif,
> +static void __ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
> const struct ath12k_wmi_p2p_noa_info *noa)
> {
> struct ath12k *ar = arvif->ar;
> @@ -105,7 +105,7 @@ static void __ath12k_p2p_noa_update(struct ath12k_vif *arvif,
> ath12k_p2p_noa_ie_assign(arvif, ie, len);
> }
>
> -void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
> +void ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
> const struct ath12k_wmi_p2p_noa_info *noa)
> {
> struct ath12k *ar = arvif->ar;
> @@ -118,9 +118,12 @@ void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
> static void ath12k_p2p_noa_update_vdev_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_p2p_noa_arg *arg = data;
> + struct ath12k_link_vif *arvif;
>
> + WARN_ON(!rcu_read_lock_any_held());
> + arvif = &ahvif->deflink;
same here.
> if (arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
> return;
>
> diff --git a/drivers/net/wireless/ath/ath12k/p2p.h b/drivers/net/wireless/ath/ath12k/p2p.h
> index b2eec51a9900..03ee877e6d6b 100644
> --- a/drivers/net/wireless/ath/ath12k/p2p.h
> +++ b/drivers/net/wireless/ath/ath12k/p2p.h
> @@ -16,7 +16,7 @@ struct ath12k_p2p_noa_arg {
> const struct ath12k_wmi_p2p_noa_info *noa;
> };
>
> -void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
> +void ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
> const struct ath12k_wmi_p2p_noa_info *noa);
> void ath12k_p2p_noa_update_by_vdev_id(struct ath12k *ar, u32 vdev_id,
> const struct ath12k_wmi_p2p_noa_info *noa);
> diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
> index 19c0626fbff1..6481f100e6cc 100644
> --- a/drivers/net/wireless/ath/ath12k/peer.c
> +++ b/drivers/net/wireless/ath/ath12k/peer.c
> @@ -1,7 +1,7 @@
> // SPDX-License-Identifier: BSD-3-Clause-Clear
> /*
> * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
> - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
> */
>
> #include "core.h"
> @@ -261,10 +261,11 @@ static int ath12k_wait_for_peer_created(struct ath12k *ar, int vdev_id, const u8
> return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, true);
> }
>
> -int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
> +int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
> struct ieee80211_sta *sta,
> struct ath12k_wmi_peer_create_arg *arg)
> {
> + struct ieee80211_vif *vif = ath12k_vif_to_vif(arvif->ahvif);
> struct ath12k_peer *peer;
> int ret;
>
> @@ -326,7 +327,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
> peer->pdev_idx = ar->pdev_idx;
> peer->sta = sta;
>
> - if (arvif->vif->type == NL80211_IFTYPE_STATION) {
> + if (vif->type == NL80211_IFTYPE_STATION) {
> arvif->ast_hash = peer->ast_hash;
> arvif->ast_idx = peer->hw_peer_id;
> }
> diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
> index 7b3500b5c8c2..b955f0cdf598 100644
> --- a/drivers/net/wireless/ath/ath12k/peer.h
> +++ b/drivers/net/wireless/ath/ath12k/peer.h
> @@ -1,7 +1,7 @@
> /* SPDX-License-Identifier: BSD-3-Clause-Clear */
> /*
> * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
> - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> */
>
> #ifndef ATH12K_PEER_H
> @@ -59,7 +59,7 @@ struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab,
> struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id);
> void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id);
> int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr);
> -int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
> +int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
> struct ieee80211_sta *sta,
> struct ath12k_wmi_peer_create_arg *arg);
> int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
> index d6e1d1398cdb..ef02c90f63b8 100644
> --- a/drivers/net/wireless/ath/ath12k/wmi.c
> +++ b/drivers/net/wireless/ath/ath12k/wmi.c
> @@ -6683,7 +6683,8 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
> const u32 *vdev_ids)
> {
> int i;
> - struct ath12k_vif *arvif;
> + struct ath12k_link_vif *arvif;
> + struct ath12k_vif *ahvif;
>
> /* Finish CSA once the switch count becomes NULL */
> if (ev->current_switch_count)
> @@ -6698,9 +6699,10 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
> vdev_ids[i]);
> continue;
> }
> + ahvif = arvif->ahvif;
>
> - if (arvif->is_up && arvif->vif->bss_conf.csa_active)
> - ieee80211_csa_finish(arvif->vif, 0);
> + if (arvif->is_up && ahvif->vif->bss_conf.csa_active)
> + ieee80211_csa_finish(ahvif->vif, 0);
> }
> rcu_read_unlock();
> }
> @@ -7252,13 +7254,13 @@ ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,
>
> int ath12k_wmi_simulate_radar(struct ath12k *ar)
> {
> - struct ath12k_vif *arvif;
> + struct ath12k_link_vif *arvif;
> u32 dfs_args[DFS_MAX_TEST_ARGS];
> struct wmi_unit_test_cmd wmi_ut;
> bool arvif_found = false;
>
> list_for_each_entry(arvif, &ar->arvifs, list) {
> - if (arvif->is_started && arvif->vdev_type == WMI_VDEV_TYPE_AP) {
> + if (arvif->is_started && arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
> arvif_found = true;
> break;
> }
More information about the ath12k
mailing list