Commit 3dd2c68f authored by Sriram R's avatar Sriram R Committed by Jeff Johnson
Browse files

wifi: ath12k: prepare vif data structure for MLO handling



To prepare the driver for MLO support, split the driver vif data structure to
scale for multiple links. This requires changing the use of arvif to per link
and not per hw which can now comprise of multiple links. Also since most
configurations from mac80211 are done per link, do refactoring of the driver
functions to apply these configurations at link level.

Split ath12k_vif which is the driver private of ieee80211_vif to store link
specific information as ath12k_link_vif. For default use cases the ath12k vif
will have a preallocated link vif called deflink which will be used by non ML
and the first link vif of ML vif.

With MLO support to be added, remaining link vifs will be allocated during
channel assignment where vdev create/start happens. These link vifs will be
freed during interface down.

       		Current ath12k_vif(arvif) structure

             +---------------+      +---------------+     +---------------+
             | ieee80211_vif |      | ieee80211_vif |     | ieee80211_vif |
             | private data  |      | private data  |     | private data  |
             |               |      |               |     |               |
             |  ath12k_vif   |      |  ath12k_vif   |     |  ath12k_vif   |
             |  (arvif)      |      |  (arvif)      |     |  (arvif)      |
             |               |      |               |     |               |
             |  +----------+ |      |  +----------+ |     |  +----------+ |
             |  |*ar (2GHz)| |      |  |*ar (5GHz)| |     |  |*ar (2GHz)| |
             |  +----------+ |      |  +----------+ |     |  +----------+ |
             |               |      |               |     |               |
             +---------------+      +---------------+     +---------------+

The new ath12k_vif (ahvif) containing ath12k_link_vif(s) (arvif) (deflink is
preallocated member which is always the first link if ieee80211_vif is MLD and
is the only link otherwise):

       			+---------------------------------+
       			|     ieee80211_vif               |
       			|     private data                |
       			|                                 |
       			|   ath12k_vif(ahvif)             |
       			|                                 |
       			| +-------------------------------+
       			| |ath12k_link_vif deflink (arvif)|
       			| |        +---------------+      |
       			| |        | *ar(2GHz)     |      |
       			| +-------------------------------+
       			| +-------------------------------+
       			| |  ath12k_link_vif *link (arvif)|
       			| |        +---------------+      |
       			| |        | *ar(5GHz)     |      |
       			| +-------------------------------+
       			| +-------------------------------+
       			| |  ath12k_link_vif *link (arvif)|
       			| |        +---------------+      |
       			| |        | *ar(6GHz)     |      |
       			| +-------------------------------+
       			|                                 |
       			+---------------------------------+

To refactor existing ath12k_vif to make use of link vifs, following
changes are made:

 1. ath12k_vif now called by variable name ahvif storing multiple
    arvifs (struct ah12k_link_vif) and also has a back pointer to ieee80211_vif.

 2. In this patch set, only deflink is used to be on par with the
    existing code. When MLO support is added the link id will be used to fetch
    the arvif.

 3. For mac80211 ops which doesn't use specific link_id, the config or info
    is common for the vif, hence apply the config to all link vifs.
    The links_map in the ahvif, will be used to identify all the link vifs that
    are setup.

 4. Change ath12k_vif_to_arvif() as ath12k_vif_to_ahvif() to fetch the
    hw level vif. The link vif can be fetched from ahvif->link[], or the
    deflink can be accessed via ahvif->deflink. API to access link
    vif (arvif) by passing link_id can be introduced with MLO Support.

 5. The ieee80211_vif can be accessed from ahvif using ath12k_ahvif_to_vif().

The locking continues to use wiphy_lock() for protecting access to most data in
struct ath12k&co, there are no changes in that regard. Though struct
ath12k_vif::link[] is protected with RCU.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Signed-off-by: default avatarSriram R <quic_srirrama@quicinc.com>
Co-developed-by: default avatarRameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: default avatarRameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://patch.msgid.link/20241015171416.518022-2-kvalo@kernel.org


Signed-off-by: default avatarJeff Johnson <quic_jjohnson@quicinc.com>
parent 25ff1ae5
Loading
Loading
Loading
Loading
+43 −23
Original line number Diff line number Diff line
@@ -239,10 +239,8 @@ struct ath12k_rekey_data {
	bool enable_offload;
};

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;
@@ -252,13 +250,39 @@ 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_rekey_data rekey_data;
};

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;
@@ -276,25 +300,15 @@ 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;
	u32 key_cipher;
	u8 tx_encap_type;
	u8 vdev_stats_id;
	u32 punct_bitmap;
	bool ps;
	struct ath12k_vif_cache *cache;
	struct ath12k_rekey_data rekey_data;

	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;

	/* Must be last - ends in a flexible-array member.
	 *
@@ -307,7 +321,7 @@ struct ath12k_vif {
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
@@ -443,7 +457,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_* */
@@ -565,7 +579,7 @@ struct ath12k {
	bool monitor_present;

	/* 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;
@@ -664,6 +678,7 @@ struct ath12k_hw {
	enum ath12k_hw_state state;
	bool regd_updated;
	bool use_6ghz_regd;

	u8 num_radio;

	/* Keep last */
@@ -1026,7 +1041,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;
}
@@ -1036,6 +1051,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_ahvif_to_vif(struct ath12k_vif *ahvif)
{
	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)
{
+12 −9
Original line number Diff line number Diff line
@@ -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;

+2 −1
Original line number Diff line number Diff line
@@ -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;

@@ -1799,7 +1800,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);
+1 −1
Original line number Diff line number Diff line
@@ -1091,7 +1091,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)
+1 −1
Original line number Diff line number Diff line
@@ -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);
Loading