Переглянути джерело

qcacmn: Add logic to wait for wds del resp before peer create

WDS entry should be removed before adding peer with same mac address.
iIn DBDC mode, this can be ensured only by waiting for response for WDS
delete from FW before creating peer. Add logic to defer AUTH until WDS
is removed from FW.

Change-Id: Ie76d08c4817f953504913ae6cc49fc5388169e4a
CRs-Fixed: 2270592
Kiran Venkatappa 6 роки тому
батько
коміт
ed35f4499d

+ 74 - 0
dp/inc/cdp_txrx_cmn.h

@@ -520,6 +520,80 @@ static inline void cdp_peer_ast_set_type
 	soc->ops->cmn_drv_ops->txrx_peer_ast_set_type(soc, ast_handle, type);
 }
 
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+static inline void cdp_peer_ast_set_cp_ctx(struct cdp_soc_t *soc,
+					   void *ast_handle,
+					   void *cp_ctx)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "Invalid Instance:");
+		QDF_BUG(0);
+		return;
+	}
+
+	if (!soc->ops->cmn_drv_ops ||
+	    !soc->ops->cmn_drv_ops->txrx_peer_ast_set_cp_ctx)
+		return;
+
+	soc->ops->cmn_drv_ops->txrx_peer_ast_set_cp_ctx(soc, ast_handle,
+							cp_ctx);
+}
+
+static inline void *cdp_peer_ast_get_cp_ctx(struct cdp_soc_t *soc,
+					    void *ast_handle)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "Invalid Instance:");
+		QDF_BUG(0);
+		return NULL;
+	}
+
+	if (!soc->ops->cmn_drv_ops ||
+	    !soc->ops->cmn_drv_ops->txrx_peer_ast_get_cp_ctx)
+		return NULL;
+
+	return soc->ops->cmn_drv_ops->txrx_peer_ast_get_cp_ctx(soc, ast_handle);
+}
+
+static inline bool cdp_peer_ast_get_wmi_sent(struct cdp_soc_t *soc,
+					     void *ast_handle)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "Invalid Instance:");
+		QDF_BUG(0);
+		return false;
+	}
+
+	if (!soc->ops->cmn_drv_ops ||
+	    !soc->ops->cmn_drv_ops->txrx_peer_ast_get_wmi_sent)
+		return false;
+
+	return soc->ops->cmn_drv_ops->txrx_peer_ast_get_wmi_sent(soc,
+								 ast_handle);
+}
+
+static inline
+void cdp_peer_ast_free_entry(struct cdp_soc_t *soc,
+			     void *ast_handle)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "Invalid Instance:");
+		QDF_BUG(0);
+		return;
+	}
+
+	if (!soc->ops->cmn_drv_ops ||
+	    !soc->ops->cmn_drv_ops->txrx_peer_ast_free_entry)
+		return;
+
+	soc->ops->cmn_drv_ops->txrx_peer_ast_free_entry(soc, ast_handle);
+}
+#endif
+
 static inline void cdp_peer_teardown
 	(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, void *peer)
 {

+ 17 - 0
dp/inc/cdp_txrx_ops.h

@@ -118,6 +118,20 @@ struct cdp_cmn_ops {
 	void (*txrx_peer_ast_set_type)
 		(ol_txrx_soc_handle soc, void *ast_hdl,
 		enum cdp_txrx_ast_entry_type type);
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+	void (*txrx_peer_ast_set_cp_ctx)(ol_txrx_soc_handle soc,
+					 void *ast_entry,
+					 void *cp_ctx);
+
+	void * (*txrx_peer_ast_get_cp_ctx)(ol_txrx_soc_handle soc,
+					   void *ast_entry);
+
+	bool (*txrx_peer_ast_get_wmi_sent)(ol_txrx_soc_handle soc,
+					   void *ast_entry);
+
+	void (*txrx_peer_ast_free_entry)(ol_txrx_soc_handle soc,
+					 void *ast_entry);
+#endif
 
 	enum cdp_txrx_ast_entry_type (*txrx_peer_ast_get_type)
 		(ol_txrx_soc_handle soc, void *ast_hdl);
@@ -803,6 +817,9 @@ struct ol_if_ops {
 			uint32_t flags);
 	void (*peer_del_wds_entry)(void *ol_soc_handle,
 			uint8_t *wds_macaddr);
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+	void (*peer_del_wds_cp_ctx)(void *cp_ctx);
+#endif
 	QDF_STATUS
 	(*lro_hash_config)(struct wlan_objmgr_psoc *ctrl_psoc,
 			   struct cdp_lro_hash_config *rx_offld_hash);

+ 58 - 0
dp/wifi3.0/dp_main.c

@@ -644,6 +644,58 @@ static enum cdp_txrx_ast_entry_type dp_peer_ast_get_type_wifi3(
 	return ((struct dp_ast_entry *)ast_entry_hdl)->type;
 }
 
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+void dp_peer_ast_set_cp_ctx_wifi3(struct cdp_soc_t *soc_handle,
+				  void *ast_entry,
+				  void *cp_ctx)
+{
+	struct dp_soc *soc = (struct dp_soc *)soc_handle;
+
+	qdf_spin_lock_bh(&soc->ast_lock);
+	dp_peer_ast_set_cp_ctx(soc,
+			       (struct dp_ast_entry *)ast_entry, cp_ctx);
+	qdf_spin_unlock_bh(&soc->ast_lock);
+}
+
+void *dp_peer_ast_get_cp_ctx_wifi3(struct cdp_soc_t *soc_handle,
+				   void *ast_entry)
+{
+	struct dp_soc *soc = (struct dp_soc *)soc_handle;
+	void *cp_ctx = NULL;
+
+	qdf_spin_lock_bh(&soc->ast_lock);
+	cp_ctx = dp_peer_ast_get_cp_ctx(soc,
+					(struct dp_ast_entry *)ast_entry);
+	qdf_spin_unlock_bh(&soc->ast_lock);
+
+	return cp_ctx;
+}
+
+bool dp_peer_ast_get_wmi_sent_wifi3(struct cdp_soc_t *soc_handle,
+				    void *ast_entry)
+{
+	struct dp_soc *soc = (struct dp_soc *)soc_handle;
+	bool wmi_sent = false;
+
+	qdf_spin_lock_bh(&soc->ast_lock);
+	wmi_sent = dp_peer_ast_get_wmi_sent(soc,
+					    (struct dp_ast_entry *)ast_entry);
+	qdf_spin_unlock_bh(&soc->ast_lock);
+
+	return wmi_sent;
+}
+
+void dp_peer_ast_free_entry_wifi3(struct cdp_soc_t *soc_handle,
+				  void *ast_entry)
+{
+	struct dp_soc *soc = (struct dp_soc *)soc_handle;
+
+	qdf_spin_lock_bh(&soc->ast_lock);
+	dp_peer_ast_free_entry(soc, (struct dp_ast_entry *)ast_entry);
+	qdf_spin_unlock_bh(&soc->ast_lock);
+}
+#endif
+
 /**
  * dp_srng_find_ring_in_mask() - find which ext_group a ring belongs
  * @ring_num: ring num of the ring being queried
@@ -7699,6 +7751,12 @@ static struct cdp_cmn_ops dp_ops_cmn = {
 	.txrx_peer_ast_get_next_hop = dp_peer_ast_get_next_hop_wifi3,
 	.txrx_peer_ast_set_type = dp_peer_ast_set_type_wifi3,
 	.txrx_peer_ast_get_type = dp_peer_ast_get_type_wifi3,
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+	.txrx_peer_ast_set_cp_ctx = dp_peer_ast_set_cp_ctx_wifi3,
+	.txrx_peer_ast_get_cp_ctx = dp_peer_ast_get_cp_ctx_wifi3,
+	.txrx_peer_ast_get_wmi_sent = dp_peer_ast_get_wmi_sent_wifi3,
+	.txrx_peer_ast_free_entry = dp_peer_ast_free_entry_wifi3,
+#endif
 	.txrx_peer_delete = dp_peer_delete_wifi3,
 	.txrx_vdev_register = dp_vdev_register_wifi3,
 	.txrx_soc_detach = dp_soc_detach_wifi3,

+ 83 - 0
dp/wifi3.0/dp_peer.c

@@ -225,6 +225,21 @@ static int dp_peer_ast_hash_attach(struct dp_soc *soc)
 	return 0;
 }
 
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+static inline void dp_peer_ast_cleanup(struct dp_soc *soc,
+				       struct dp_ast_entry *ast)
+{
+	struct cdp_soc_t *cdp_soc = &soc->cdp_soc;
+
+	if (ast->cp_ctx && cdp_soc->ol_ops->peer_del_wds_cp_ctx)
+		cdp_soc->ol_ops->peer_del_wds_cp_ctx(ast->cp_ctx);
+}
+#else
+static inline void dp_peer_ast_cleanup(struct dp_soc *soc,
+				       struct dp_ast_entry *ast)
+{
+}
+#endif
 /*
  * dp_peer_ast_hash_detach() - Free AST Hash table
  * @soc: SoC handle
@@ -529,6 +544,22 @@ int dp_peer_add_ast(struct dp_soc *soc,
 	return ret;
 }
 
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry)
+{
+	struct dp_peer *peer = ast_entry->peer;
+
+	if (ast_entry->next_hop) {
+		dp_peer_ast_send_wds_del(soc, ast_entry);
+	} else {
+		soc->ast_table[ast_entry->ast_idx] = NULL;
+		TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem);
+		DP_STATS_INC(soc, ast.deleted, 1);
+		dp_peer_ast_hash_remove(soc, ast_entry);
+		qdf_mem_free(ast_entry);
+	}
+}
+#else
 /*
  * dp_peer_del_ast() - Delete and free AST entry
  * @soc: SoC handle
@@ -558,6 +589,7 @@ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry)
 	dp_peer_ast_hash_remove(soc, ast_entry);
 	qdf_mem_free(ast_entry);
 }
+#endif
 
 /*
  * dp_peer_update_ast() - Delete and free AST entry
@@ -708,6 +740,57 @@ uint8_t dp_peer_ast_get_next_hop(struct dp_soc *soc,
 }
 #endif
 
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+void dp_peer_ast_set_cp_ctx(struct dp_soc *soc,
+			    struct dp_ast_entry *ast_entry,
+			    void *cp_ctx)
+{
+	ast_entry->cp_ctx = cp_ctx;
+}
+
+void *dp_peer_ast_get_cp_ctx(struct dp_soc *soc,
+			     struct dp_ast_entry *ast_entry)
+{
+	void *cp_ctx = NULL;
+
+	cp_ctx = ast_entry->cp_ctx;
+	ast_entry->cp_ctx = NULL;
+
+	return cp_ctx;
+}
+
+void dp_peer_ast_send_wds_del(struct dp_soc *soc,
+			      struct dp_ast_entry *ast_entry)
+{
+	struct dp_peer *peer = ast_entry->peer;
+	struct cdp_soc_t *cdp_soc = &soc->cdp_soc;
+
+	if (!ast_entry->wmi_sent) {
+		cdp_soc->ol_ops->peer_del_wds_entry(peer->vdev->osif_vdev,
+						    ast_entry->mac_addr.raw);
+		ast_entry->wmi_sent = true;
+	}
+}
+
+bool dp_peer_ast_get_wmi_sent(struct dp_soc *soc,
+			      struct dp_ast_entry *ast_entry)
+{
+	return ast_entry->wmi_sent;
+}
+
+void dp_peer_ast_free_entry(struct dp_soc *soc,
+			    struct dp_ast_entry *ast_entry)
+{
+	struct dp_peer *peer = ast_entry->peer;
+
+	soc->ast_table[ast_entry->ast_idx] = NULL;
+	TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem);
+	DP_STATS_INC(soc, ast.deleted, 1);
+	dp_peer_ast_hash_remove(soc, ast_entry);
+	qdf_mem_free(ast_entry);
+}
+#endif
+
 struct dp_peer *dp_peer_find_hash_find(struct dp_soc *soc,
 	uint8_t *peer_mac_addr, int mac_addr_is_aligned, uint8_t vdev_id)
 {

+ 19 - 0
dp/wifi3.0/dp_peer.h

@@ -107,6 +107,25 @@ void dp_peer_ast_set_type(struct dp_soc *soc,
 				struct dp_ast_entry *ast_entry,
 				enum cdp_txrx_ast_entry_type type);
 
+#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND)
+void dp_peer_ast_set_cp_ctx(struct dp_soc *soc,
+			    struct dp_ast_entry *ast_entry,
+			    void *cp_ctx);
+
+void *dp_peer_ast_get_cp_ctx(struct dp_soc *soc,
+			     struct dp_ast_entry *ast_entry);
+
+void dp_peer_ast_send_wds_del(struct dp_soc *soc,
+			      struct dp_ast_entry *ast_entry);
+
+bool dp_peer_ast_get_wmi_sent(struct dp_soc *soc,
+			      struct dp_ast_entry *ast_entry);
+
+void dp_peer_ast_free_entry(struct dp_soc *soc,
+			    struct dp_ast_entry *ast_entry);
+
+#endif
+
 /*
  * dp_get_vdev_from_soc_vdev_id_wifi3() -
  * Returns vdev object given the vdev id

+ 6 - 0
dp/wifi3.0/dp_types.h

@@ -622,6 +622,8 @@ union dp_align_mac_addr {
  * @ast_hash_value: hast value in HW
  * @ref_cnt: reference count
  * @type: flag to indicate type of the entry(static/WDS/MEC)
+ * @wmi_sent: Flag to identify of WMI to del ast is sent (AST_HKV1_WORKAROUND)
+ * @cp_ctx: Opaque context used by control path (AST_HKV1_WORKAROUND)
  * @hash_list_elem: node in soc AST hash list (mac address used as hash)
  */
 struct dp_ast_entry {
@@ -637,6 +639,10 @@ struct dp_ast_entry {
 	uint16_t ast_hash_value;
 	qdf_atomic_t ref_cnt;
 	enum cdp_txrx_ast_entry_type type;
+#ifdef AST_HKV1_WORKAROUND
+	bool wmi_sent;
+	void *cp_ctx;
+#endif
 	TAILQ_ENTRY(dp_ast_entry) ase_list_elem;
 	TAILQ_ENTRY(dp_ast_entry) hash_list_elem;
 };

+ 5 - 0
wmi/src/wmi_unified_tlv.c

@@ -20574,6 +20574,8 @@ static QDF_STATUS extract_wds_addr_event_tlv(wmi_unified_t wmi_handle,
 		wds_ev->dest_mac[4+i] =
 			((u_int8_t *)&(ev->dest_mac.mac_addr47to32))[i];
 	}
+	wds_ev->vdev_id = ev->vdev_id;
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -23242,6 +23244,9 @@ static void populate_tlv_events_id(uint32_t *event_ids)
 	event_ids[wmi_wlan_sar2_result_event_id] = WMI_SAR2_RESULT_EVENTID;
 	event_ids[wmi_esp_estimate_event_id] = WMI_ESP_ESTIMATE_EVENTID;
 	event_ids[wmi_roam_scan_stats_event_id] = WMI_ROAM_SCAN_STATS_EVENTID;
+#ifdef AST_HKV1_WORKAROUND
+	event_ids[wmi_wds_peer_event_id] = WMI_WDS_PEER_EVENTID;
+#endif
 }
 
 /**