From 730f568af3fac2f31467ea0ff374ea442ddc379f Mon Sep 17 00:00:00 2001
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
Date: Fri, 20 Nov 2020 11:57:36 +0530
Subject: [PATCH 3/3] ath11k: add AP_VLAN vif support for WDS offload in NSS
 offload

- AP_VLAN vif support is required for WDS offload to interop with mac80211
  based 4addr STA and also for multicast-to-unicast conversion of 3addr
  multicast to 4addr frames for each associated 4addr STA.

- For each associated 4addr STA, corresponding AP_VLAN vif having same MAC
  address as AP vif is created from hostapd upon 4addr rx_notify from NSS RX.

- AP_VLAN vif support is added to add/remove interface mac80211 callbacks only
  for NSS ext vdev handling and vdev_id, FW vdev operations are not needed.

- mac80211 advertises AP_VLAN vif for sta_use_4addr drv callback in case of
  NSS offload. Extending ath11k_mac_op_sta_use_4addr to invoke ext vdev NSS
  APIs required for AP WDS handling.

- Maintain AP_VLAN vif(s) list on corresponding AP vif and vice versa required
  for ext vdev operations (VDEV_DOWN, DELETE, CONFIGURE_IF).

- NSS require ENABLE_NAWDS and WDS_BACKHAUL to be configured for AP_VLAN
  support via ext vdev.

Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.h |   1 +
 drivers/net/wireless/ath/ath11k/mac.c  | 156 +++++++++++++++++++++++++++++++--
 drivers/net/wireless/ath/ath11k/wmi.h  |   2 +
 3 files changed, 154 insertions(+), 5 deletions(-)

--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -276,6 +276,7 @@ struct ath11k_vif {
 	struct ath11k_mgmt_frame_stats mgmt_stats;
 #ifdef CPTCFG_ATH11K_NSS_SUPPORT
 	struct arvif_nss nss;
+	struct list_head ap_vlan_arvifs;
 #endif
 };
 
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -4233,6 +4233,11 @@ static void ath11k_sta_rc_update_wk(stru
 	arvif = arsta->arvif;
 	ar = arvif->ar;
 
+	if (ar->ab->nss.enabled &&
+	    arsta->arvif->vif->type == NL80211_IFTYPE_AP_VLAN &&
+	    arsta->use_4addr_set)
+		arvif = arvif->nss.ap_vif;
+
 	if (WARN_ON(ath11k_mac_vif_chan(arvif->vif, &def)))
 		return;
 
@@ -4350,26 +4355,130 @@ static void ath11k_sta_rc_update_wk(stru
 static void ath11k_sta_use_4addr_wk(struct work_struct *wk)
 {
 	struct ath11k *ar;
-	struct ath11k_vif *arvif;
+	struct ath11k_vif *arvif, *ap_vlan_arvif = NULL;
+	struct ieee80211_vif *vif;
 	struct ath11k_sta *arsta;
 	struct ieee80211_sta *sta;
+	struct ath11k_base *ab;
+	struct ath11k_peer *wds_peer;
+	u8 wds_addr[ETH_ALEN];
+	u32 wds_peer_id;
 	int ret = 0;
 
 	arsta = container_of(wk, struct ath11k_sta, use_4addr_wk);
 	sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
 	arvif = arsta->arvif;
 	ar = arvif->ar;
+	ab = ar->ab;
 
-	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
-		   "setting USE_4ADDR for STA %pM\n", sta->addr);
+	if (ab->nss.enabled && arvif->vif->type == NL80211_IFTYPE_AP_VLAN) {
+		ap_vlan_arvif = arsta->arvif;
+		arvif = ap_vlan_arvif->nss.ap_vif;
+	}
+
+	ath11k_dbg(ab, ATH11K_DBG_MAC,
+		   "setting USE_4ADDR for peer %pM\n", sta->addr);
 
 	ret = ath11k_wmi_set_peer_param(ar, sta->addr,
 					arvif->vdev_id,
 					WMI_PEER_USE_4ADDR, 1);
 
 	if (ret)
-		ath11k_warn(ar->ab, "failed to set 4addr for STA %pM: %d\n",
+		ath11k_warn(ab, "failed to set 4addr for STA %pM: %d\n",
 			    sta->addr, ret);
+
+	if (!ab->nss.enabled || !ap_vlan_arvif)
+		return;
+
+	vif = ap_vlan_arvif->vif;
+
+	spin_lock_bh(&ab->base_lock);
+	wds_peer = ath11k_peer_find_by_addr(ab, sta->addr);
+	if (!wds_peer) {
+		spin_unlock_bh(&ab->base_lock);
+		ath11k_warn(ab, "mac sta use 4addr failed to find peer %pM\n",
+			    sta->addr);
+		return;
+	}
+
+	wds_peer_id = wds_peer->peer_id;
+	ether_addr_copy(wds_addr, wds_peer->addr);
+	spin_unlock_bh(&ab->base_lock);
+
+	/* skip NSS ext vdev registration if already done */
+	if (ap_vlan_arvif->nss.wds_cfg_done)
+		goto skip_nss_ext;
+
+	ret = ath11k_nss_ext_vdev_configure(ap_vlan_arvif);
+	if (ret) {
+		ath11k_warn(ab, "failed to nss cfg ext vdev %pM: %d\n",
+			    vif->addr, ret);
+		goto ext_vdev_delete;
+	}
+
+	ap_vlan_arvif->nss.wds_cfg_done = true;
+
+skip_nss_ext:
+
+	ret = ath11k_nss_ext_vdev_cfg_wds_peer(ap_vlan_arvif,
+					       wds_addr, wds_peer_id);
+	if (ret) {
+		ath11k_warn(ab, "failed to nss cfg_wds_peer %pM on %pM: %d\n",
+			    sta->addr, vif->addr, ret);
+		goto ext_vdev_delete;
+	}
+
+	ret = ath11k_nss_ext_vdev_wds_4addr_allow(ap_vlan_arvif,
+						  wds_peer_id);
+	if (ret) {
+		ath11k_warn(ab, "failed to nss 4addr allow %pM: %d\n",
+			    vif->addr, ret);
+		goto ext_vdev_delete;
+	}
+
+	ret = ath11k_nss_ext_vdev_up(ap_vlan_arvif);
+	if (ret) {
+		ath11k_warn(ab, "failed to nss ext vdev up %pM: %d\n",
+			    vif->addr, ret);
+		goto ext_vdev_delete;
+	}
+
+	spin_lock_bh(&ab->base_lock);
+	wds_peer->nss.ext_vdev_up = true;
+	spin_unlock_bh(&ab->base_lock);
+
+	/* NAWDS and CFG_WDS_BACKHAUL configs should be done on corresponding
+	 * AP vif of the AP_VLAN vif
+	 */
+	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+					    WMI_VDEV_PARAM_AP_ENABLE_NAWDS,
+					    MIN_IDLE_INACTIVE_TIME_SECS);
+	if (ret) {
+		ath11k_warn(ab, "failed to set vdev %i nawds parameters: %d\n",
+			    arvif->vdev_id, ret);
+		goto ext_vdev_down;
+	}
+
+	ret = ath11k_nss_vdev_set_cmd(arvif,
+				      NSS_WIFI_VDEV_CFG_WDS_BACKHAUL_CMD,
+				      true);
+	if (ret) {
+		ath11k_warn(ab, "failed to cfg wds backhaul in nss %d\n",
+			    ret);
+		goto ext_vdev_down;
+	}
+
+	return;
+
+ext_vdev_down:
+	ath11k_nss_ext_vdev_down(ap_vlan_arvif);
+ext_vdev_delete:
+	ath11k_nss_ext_vdev_delete(ap_vlan_arvif);
+
+	spin_lock_bh(&ar->data_lock);
+	list_del(&ap_vlan_arvif->list);
+	spin_unlock_bh(&ar->data_lock);
+	ap_vlan_arvif->nss.added = false;
 }
 
 static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
@@ -4670,9 +4779,32 @@ static void ath11k_mac_op_sta_set_4addr(
                                        bool enabled)
 {
 	struct ath11k *ar = hw->priv;
+	struct ath11k_vif *arvif = (void *)vif->drv_priv;
 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
+	struct ath11k_vif *ap_arvif = NULL;
 
 	if (enabled && !arsta->use_4addr_set) {
+		if (ar->ab->nss.enabled && vif->type == NL80211_IFTYPE_AP_VLAN) {
+			/* 4addr STA is initially associated to AP vif, change
+			 * it to AP_VLAN vif and add AP_VLAN vif to AP vifs list
+			 */
+			ap_arvif = arsta->arvif;
+			arvif->nss.ap_vif = ap_arvif;
+
+			/* Check if the vlan arvif object was already present in the
+			 * list. We can receive this path multiple times for the same
+			 * vlan vif for different sta objects
+			 */
+			if (!arvif->nss.added) {
+				spin_lock_bh(&ar->data_lock);
+				list_add(&arvif->list, &ap_arvif->ap_vlan_arvifs);
+				spin_unlock_bh(&ar->data_lock);
+				arvif->nss.added = true;
+			}
+
+			arsta->arvif = arvif;
+		}
+
 		ieee80211_queue_work(ar->hw, &arsta->use_4addr_wk);
 		arsta->use_4addr_set = true;
 	}
@@ -5997,6 +6129,9 @@ static void ath11k_mac_op_update_vif_off
 	u32 param_id, param_value;
 	int ret;
 
+	if (ab->nss.enabled && vif->type == NL80211_IFTYPE_AP_VLAN)
+		return 0;
+
 	ret = ath11k_nss_vdev_create(arvif);
 	if(ret) {
 		ath11k_warn(ab, "failed to create nss vdev %d\n", ret);
@@ -6067,7 +6202,8 @@ static int ath11k_mac_op_add_interface(s
 		goto err;
 	}
 
-	if (ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) {
+	if (vif->type != NL80211_IFTYPE_AP_VLAN  &&
+	     ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) {
 		ath11k_warn(ab, "failed to create vdev %u, reached max vdev limit %d\n",
 			    ar->num_created_vdevs, TARGET_NUM_VDEVS);
 		ret = -EBUSY;
@@ -6080,6 +6216,28 @@ static int ath11k_mac_op_add_interface(s
 	arvif->vif = vif;
 
 	INIT_LIST_HEAD(&arvif->list);
+
+	if ((vif->type == NL80211_IFTYPE_AP_VLAN ||
+	     vif->type == NL80211_IFTYPE_STATION) && ab->nss.enabled) {
+		if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET &&
+		    ieee80211_set_hw_80211_encap(vif, true)) {
+			vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
+			arvif->nss.encap = ATH11K_HW_TXRX_ETHERNET;
+			arvif->nss.decap = ATH11K_HW_TXRX_ETHERNET;
+		}
+
+		if (vif->type == NL80211_IFTYPE_AP_VLAN) {
+			ret = ath11k_nss_ext_vdev_create(arvif);
+			if (ret) {
+				ath11k_warn(ab, "failed to create ext vdev %pM: %d\n",
+					    vif->addr, ret);
+				goto err;
+			}
+			mutex_unlock(&ar->conf_mutex);
+			return ret;
+		}
+	}
+
 	INIT_DELAYED_WORK(&arvif->connection_loss_work,
                           ath11k_mac_vif_sta_connection_loss_work);
 
@@ -6109,6 +6267,7 @@ static int ath11k_mac_op_add_interface(s
 		fallthrough;
 	case NL80211_IFTYPE_AP:
 		arvif->vdev_type = WMI_VDEV_TYPE_AP;
+		INIT_LIST_HEAD(&arvif->ap_vlan_arvifs);
 		break;
 	case NL80211_IFTYPE_MONITOR:
 		arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
@@ -6332,15 +6491,32 @@ static void ath11k_mac_op_remove_interfa
 {
 	struct ath11k *ar = hw->priv;
 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
+	struct ath11k_vif *ap_vlan_arvif, *tmp;
 	struct ath11k_base *ab = ar->ab;
 	unsigned long time_left;
 	int ret;
 	int i;
 
-	cancel_delayed_work_sync(&arvif->connection_loss_work);
-
 	mutex_lock(&ar->conf_mutex);
 
+	if (vif->type == NL80211_IFTYPE_AP_VLAN) {
+		ath11k_nss_ext_vdev_delete(arvif);
+
+		/* In case the vlan vif never got added into the ap vlan arvifs
+		 * list, avoid removal here
+		 */
+		if (!arvif->nss.added)
+			goto unlock;
+
+		spin_lock_bh(&ar->data_lock);
+		list_del(&arvif->list);
+		spin_unlock_bh(&ar->data_lock);
+
+		goto unlock;
+	}
+
+	cancel_delayed_work_sync(&arvif->connection_loss_work);
+
 	ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
 		   arvif->vdev_id);
 
@@ -6349,6 +6525,14 @@ static void ath11k_mac_op_remove_interfa
 		if (ret)
 			ath11k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",
 				    arvif->vdev_id, ret);
+
+		list_for_each_entry_safe(ap_vlan_arvif, tmp, &arvif->ap_vlan_arvifs,
+					 list) {
+			ath11k_nss_ext_vdev_delete(ap_vlan_arvif);
+			spin_lock_bh(&ar->data_lock);
+			list_del(&ap_vlan_arvif->list);
+			spin_unlock_bh(&ar->data_lock);
+		}
 	}
 
 	reinit_completion(&ar->vdev_delete_done);
@@ -6409,7 +6593,7 @@ err_vdev_del:
 	/* Remove TWT related files and directory */
 	debugfs_remove_recursive(arvif->debugfs_twt);
 	arvif->debugfs_twt = NULL;
-
+unlock:
 	mutex_unlock(&ar->conf_mutex);
 }
 
@@ -6474,16 +6658,17 @@ static int ath11k_mac_op_ampdu_action(st
 				      struct ieee80211_ampdu_params *params)
 {
 	struct ath11k *ar = hw->priv;
+	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
 	int ret = -EINVAL;
 
 	mutex_lock(&ar->conf_mutex);
 
 	switch (params->action) {
 	case IEEE80211_AMPDU_RX_START:
-		ret = ath11k_dp_rx_ampdu_start(ar, params);
+		ret = ath11k_dp_rx_ampdu_start(arvif, params);
 		break;
 	case IEEE80211_AMPDU_RX_STOP:
-		ret = ath11k_dp_rx_ampdu_stop(ar, params);
+		ret = ath11k_dp_rx_ampdu_stop(arvif, params);
 		break;
 	case IEEE80211_AMPDU_TX_START:
 	case IEEE80211_AMPDU_TX_STOP_CONT:
@@ -7982,6 +8167,7 @@ static void ath11k_mac_op_sta_statistics
 					 struct station_info *sinfo)
 {
 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
+	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
 
 	sinfo->rx_duration = arsta->rx_duration;
 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
@@ -8009,7 +8195,8 @@ static void ath11k_mac_op_sta_statistics
 	sinfo->signal = arsta->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR;
 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
 
-	ath11k_nss_update_sta_stats(sinfo, sta, arsta);
+	if (arvif->ar->ab->nss.enabled)
+		ath11k_nss_update_sta_stats(arvif, sinfo, sta);
 }
 
 #define ATH11K_WLAN_PRIO_MAX	0x63
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -4818,6 +4818,8 @@ enum wmi_vdev_subtype {
 	WMI_VDEV_SUBTYPE_MESH_11S,
 };
 
+#define MIN_IDLE_INACTIVE_TIME_SECS 256
+
 enum wmi_sta_powersave_param {
 	WMI_STA_PS_PARAM_RX_WAKE_POLICY = 0,
 	WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD = 1,
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1093,12 +1093,13 @@ err_mem_free:
 	return ret;
 }
 
-int ath11k_dp_rx_ampdu_start(struct ath11k *ar,
+int ath11k_dp_rx_ampdu_start(struct ath11k_vif *arvif,
 			     struct ieee80211_ampdu_params *params)
 {
+	struct ath11k *ar = arvif->ar;
 	struct ath11k_base *ab = ar->ab;
 	struct ath11k_sta *arsta = (void *)params->sta->drv_priv;
-	int vdev_id = arsta->arvif->vdev_id;
+	int vdev_id = arvif->vdev_id;
 	int ret;
 
 	ret = ath11k_peer_rx_tid_setup(ar, params->sta->addr, vdev_id,
@@ -1110,13 +1111,13 @@ int ath11k_dp_rx_ampdu_start(struct ath1
 	return ret;
 }
 
-int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
+int ath11k_dp_rx_ampdu_stop(struct ath11k_vif *arvif,
 			    struct ieee80211_ampdu_params *params)
 {
+	struct ath11k *ar = arvif->ar;
 	struct ath11k_base *ab = ar->ab;
 	struct ath11k_peer *peer;
-	struct ath11k_sta *arsta = (void *)params->sta->drv_priv;
-	int vdev_id = arsta->arvif->vdev_id;
+	int vdev_id = arvif->vdev_id;
 	dma_addr_t paddr;
 	bool active;
 	int ret;
@@ -3086,11 +3087,11 @@ ath11k_dp_rx_update_peer_rate_table_stat
 		rx_stats->byte_stats.rx_rate[rate_idx] += ppdu_info->mpdu_len;
 }
 
-static void ath11k_dp_rx_update_peer_su_stats(struct ath11k_sta *arsta,
-					   struct hal_rx_mon_ppdu_info *ppdu_info)
+static void ath11k_dp_rx_update_peer_su_stats(struct ath11k *ar,
+					      struct ath11k_sta *arsta,
+					      struct hal_rx_mon_ppdu_info *ppdu_info)
 {
 	struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
-	struct ath11k *ar = arsta->arvif->ar;
 	u32 num_msdu;
 
 	if (!rx_stats)
@@ -3682,7 +3683,7 @@ int ath11k_dp_rx_process_mon_status(stru
 
 		if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
 			arsta = (struct ath11k_sta *)peer->sta->drv_priv;
-			ath11k_dp_rx_update_peer_su_stats(arsta, ppdu_info);
+			ath11k_dp_rx_update_peer_su_stats(ar, arsta, ppdu_info);
 		} else if ((ppdu_info->fc_valid) &&
 			   (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) {
 			ath11k_dp_rx_mon_process_ulofdma(ppdu_info);
--- a/drivers/net/wireless/ath/ath11k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h
@@ -60,9 +60,9 @@ static inline u32 ath11k_he_gi_to_nl8021
         return ret;
 }
 
-int ath11k_dp_rx_ampdu_start(struct ath11k *ar,
+int ath11k_dp_rx_ampdu_start(struct ath11k_vif *arvif,
 			     struct ieee80211_ampdu_params *params);
-int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
+int ath11k_dp_rx_ampdu_stop(struct ath11k_vif *arvif,
 			    struct ieee80211_ampdu_params *params);
 int ath11k_dp_peer_rx_pn_replay_config(struct ath11k_vif *arvif,
 				       const u8 *peer_addr,
--- a/drivers/net/wireless/ath/ath11k/peer.c
+++ b/drivers/net/wireless/ath/ath11k/peer.c
@@ -139,6 +139,24 @@ struct ath11k_ast_entry *ath11k_peer_ast
 	return NULL;
 }
 
+struct ath11k_ast_entry *ath11k_peer_ast_find_by_pdev_idx(struct ath11k *ar,
+							  u8* addr)
+{
+	struct ath11k_base *ab = ar->ab;
+	struct ath11k_ast_entry *ast_entry;
+	struct ath11k_peer *peer;
+
+	lockdep_assert_held(&ab->base_lock);
+
+	list_for_each_entry(peer, &ab->peers, list)
+		list_for_each_entry(ast_entry, &peer->ast_entry_list, ase_list)
+			if (ether_addr_equal(ast_entry->addr, addr) &&
+			    ast_entry->pdev_idx == ar->pdev_idx)
+				return ast_entry;
+
+	return NULL;
+}
+
 void ath11k_peer_ast_wds_wmi_wk(struct work_struct *wk)
 {
 	struct ath11k_ast_entry *ast_entry = container_of(wk,
@@ -199,8 +217,8 @@ int ath11k_peer_add_ast(struct ath11k *a
 	}
 
 	if (type != ATH11K_AST_TYPE_STATIC) {
-		ast_entry = ath11k_peer_ast_find_by_addr(ab, mac_addr);
-		if (ast_entry) {
+		ast_entry = ath11k_peer_ast_find_by_pdev_idx(ar, mac_addr);
+		if (ast_entry && ast_entry->type != ATH11K_AST_TYPE_STATIC) {
 			ath11k_dbg(ab, ATH11K_DBG_MAC, "ast_entry %pM already present on peer %pM\n",
 				   mac_addr, ast_entry->peer->addr);
 			return 0;
@@ -297,7 +315,6 @@ int ath11k_peer_update_ast(struct ath11k
 	ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_update_ast old peer %pM new peer %pM ast_entry %pM\n",
 		   old_peer->addr, peer->addr, ast_entry->addr);
 
-	flush_work(&ast_entry->wds_wmi_wk);
 	ast_entry->action = ATH11K_WDS_WMI_UPDATE;
 	ieee80211_queue_work(ar->hw, &ast_entry->wds_wmi_wk);
 
@@ -342,8 +359,8 @@ void ath11k_peer_del_ast(struct ath11k *
 
 	peer = ast_entry->peer;
 
-	ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_del_ast peer %pM ast_entry %pM\n",
-		   peer->addr, ast_entry->addr);
+	ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_del_ast pdev:%d peer %pM ast_entry %pM\n",
+		   ar->pdev->pdev_id, peer->addr, ast_entry->addr);
 
 	if (ast_entry->is_mapped)
 		list_del(&ast_entry->ase_list);
--- a/drivers/net/wireless/ath/ath11k/peer.h
+++ b/drivers/net/wireless/ath/ath11k/peer.h
@@ -34,6 +34,7 @@ enum ath11k_ast_entry_type {
 enum ath11k_wds_wmi_action {
 	ATH11K_WDS_WMI_ADD = 1,
 	ATH11K_WDS_WMI_UPDATE,
+	ATH11K_WDS_WMI_REMOVE,
 
 	ATH11K_WDS_WMI_MAX
 };
@@ -119,6 +120,8 @@ struct ath11k_peer *ath11k_peer_find_by_
 #ifdef CPTCFG_ATH11K_NSS_SUPPORT
 struct ath11k_ast_entry *ath11k_peer_ast_find_by_addr(struct ath11k_base *ab,
 						      u8* addr);
+struct ath11k_ast_entry *ath11k_peer_ast_find_by_pdev_idx(struct ath11k *ar,
+							  u8* addr);
 int ath11k_peer_add_ast(struct ath11k *ar, struct ath11k_peer *peer,
 			u8* mac_addr, enum ath11k_ast_entry_type type);
 int ath11k_peer_update_ast(struct ath11k *ar, struct ath11k_peer *peer,
@@ -138,6 +141,12 @@ static inline struct ath11k_ast_entry *a
 {
 	return NULL;
 }
+
+static inline struct ath11k_ast_entry *ath11k_peer_ast_find_by_pdev_idx(struct ath11k *ar,
+									u8* addr)
+{
+	return NULL;
+}
 
 static inline int ath11k_peer_add_ast(struct ath11k *ar, struct ath11k_peer *peer,
 				      u8* mac_addr, enum ath11k_ast_entry_type type)
