Browse Source

qcacmn: update peer reuse logic and add peer state lock

With new design, peer is deleted from hash table in
cdp_peer_delete. Hash table search in dp_peer_can_reuse
API at cdp_peer_create will always fail

Update the peer reuse logic to search from inactive list.

Insert peer to inactive list from cdp_peer_delete() and
in peer reuse case search in inactive list to get
peer.

Also add a new lock to protect peer state transition

Change-Id: I2e672fc4a9346c95d67716d437538dd0f96b2207
Chaithanya Garrepalli 4 năm trước cách đây
mục cha
commit
3ac6dedea7
4 tập tin đã thay đổi với 91 bổ sung68 xóa
  1. 36 32
      dp/wifi3.0/dp_main.c
  2. 3 9
      dp/wifi3.0/dp_peer.c
  3. 28 1
      dp/wifi3.0/dp_peer.h
  4. 24 26
      dp/wifi3.0/dp_types.h

+ 36 - 32
dp/wifi3.0/dp_main.c

@@ -5589,43 +5589,35 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc,
 	return QDF_STATUS_SUCCESS;
 }
 
-#if ATH_SUPPORT_WRAP
 static inline struct dp_peer *dp_peer_can_reuse(struct dp_vdev *vdev,
 						uint8_t *peer_mac_addr)
 {
 	struct dp_peer *peer;
+	struct dp_soc *soc = vdev->pdev->soc;
 
-	peer = dp_peer_find_hash_find(vdev->pdev->soc, peer_mac_addr,
-				      0, vdev->vdev_id,
-				      DP_MOD_ID_CONFIG);
-	if (!peer)
-		return NULL;
-
-	if (peer->bss_peer)
-		return peer;
-
-	dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
-	return NULL;
-}
-#else
-static inline struct dp_peer *dp_peer_can_reuse(struct dp_vdev *vdev,
-						uint8_t *peer_mac_addr)
-{
-	struct dp_peer *peer;
-
-	peer = dp_peer_find_hash_find(vdev->pdev->soc, peer_mac_addr,
-				      0, vdev->vdev_id,
-				      DP_MOD_ID_CONFIG);
-	if (!peer)
-		return NULL;
+	qdf_spin_lock_bh(&soc->inactive_peer_list_lock);
+	TAILQ_FOREACH(peer, &soc->inactive_peer_list,
+		      inactive_list_elem) {
 
-	if (peer->bss_peer && (peer->vdev->vdev_id == vdev->vdev_id))
-		return peer;
+		/* reuse bss peer only when vdev matches*/
+		if (peer->bss_peer && (peer->vdev == vdev) &&
+		    qdf_mem_cmp(peer_mac_addr, peer->mac_addr.raw,
+				QDF_MAC_ADDR_SIZE) == 0) {
+			/* increment ref count for cdp_peer_create*/
+			if (dp_peer_get_ref(soc, peer, DP_MOD_ID_CONFIG) ==
+						QDF_STATUS_SUCCESS) {
+				TAILQ_REMOVE(&soc->inactive_peer_list, peer,
+					     inactive_list_elem);
+				qdf_spin_unlock_bh
+					(&soc->inactive_peer_list_lock);
+				return peer;
+			}
+		}
+	}
 
-	dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
+	qdf_spin_unlock_bh(&soc->inactive_peer_list_lock);
 	return NULL;
 }
-#endif
 
 #ifdef FEATURE_AST
 static inline void dp_peer_ast_handle_roam_del(struct dp_soc *soc,
@@ -5699,9 +5691,15 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 	peer = dp_peer_can_reuse(vdev, peer_mac_addr);
 
 	if (peer) {
+		dp_peer_vdev_list_add(soc, vdev, peer);
+
+		dp_peer_find_hash_add(soc, peer);
 		qdf_atomic_init(&peer->is_default_route_set);
 		dp_peer_cleanup(vdev, peer);
 
+		for (i = 0; i < DP_MAX_TIDS; i++)
+			qdf_spinlock_create(&peer->rx_tid[i].tid_lock);
+
 		qdf_spin_lock_bh(&soc->ast_lock);
 		dp_peer_delete_ast_entries(soc, peer);
 		qdf_spin_unlock_bh(&soc->ast_lock);
@@ -5871,6 +5869,7 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 
 	dp_set_peer_isolation(peer, false);
 
+	qdf_spinlock_create(&peer->peer_state_lock);
 	dp_peer_update_state(soc, peer, DP_PEER_STATE_INIT);
 
 	dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP);
@@ -6557,7 +6556,7 @@ void dp_peer_unref_delete(struct dp_peer *peer, enum dp_mod_id mod_id)
 	struct cdp_peer_cookie peer_cookie;
 	struct dp_peer *tmp_peer;
 	bool found = false;
-	int tid;
+	int tid = 0;
 
 	if (mod_id > DP_MOD_ID_RX)
 		QDF_ASSERT(qdf_atomic_dec_return(&peer->mod_refs[mod_id]) >= 0);
@@ -6623,9 +6622,12 @@ void dp_peer_unref_delete(struct dp_peer *peer, enum dp_mod_id mod_id)
 		DP_AST_ASSERT(TAILQ_EMPTY(&peer->ast_entry_list));
 		dp_peer_update_state(soc, peer, DP_PEER_STATE_FREED);
 
+		/* cleanup the peer data */
+		dp_peer_cleanup(vdev, peer);
 		for (tid = 0; tid < DP_MAX_TIDS; tid++)
 			qdf_spinlock_destroy(&peer->rx_tid[tid].tid_lock);
 
+		qdf_spinlock_destroy(&peer->peer_state_lock);
 		qdf_mem_free(peer);
 
 		/*
@@ -6704,6 +6706,11 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl,
 
 	dp_peer_vdev_list_remove(soc, vdev, peer);
 
+	qdf_spin_lock_bh(&soc->inactive_peer_list_lock);
+	TAILQ_INSERT_TAIL(&soc->inactive_peer_list, peer,
+			  inactive_list_elem);
+	qdf_spin_unlock_bh(&soc->inactive_peer_list_lock);
+
 	/*
 	 * Remove the reference added during peer_attach.
 	 * The peer will still be left allocated until the
@@ -10064,9 +10071,6 @@ dp_peer_teardown_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (peer->peer_state == DP_PEER_STATE_INIT)
-		dp_peer_cleanup(peer->vdev, peer);
-
 	qdf_spin_lock_bh(&soc->ast_lock);
 	dp_peer_delete_ast_entries(soc, peer);
 

+ 3 - 9
dp/wifi3.0/dp_peer.c

@@ -890,7 +890,7 @@ QDF_STATUS dp_peer_add_ast(struct dp_soc *soc,
 
 	qdf_spin_lock_bh(&soc->ast_lock);
 
-	if (peer->peer_state != DP_PEER_STATE_ACTIVE) {
+	if (!dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE)) {
 		if ((type != CDP_TXRX_AST_TYPE_STATIC) &&
 		    (type != CDP_TXRX_AST_TYPE_SELF)) {
 			qdf_spin_unlock_bh(&soc->ast_lock);
@@ -1319,7 +1319,7 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer,
 	 *  3) We did not get the HTT map for create event
 	 */
 	if (ast_entry->delete_in_progress ||
-	    (peer->peer_state != DP_PEER_STATE_ACTIVE) ||
+	    !dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE) ||
 	    !ast_entry->is_mapped)
 		return ret;
 
@@ -1983,7 +1983,7 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc,
 		 * if peer is in logical delete CP triggered delete before map
 		 * is received ignore this event
 		 */
-		if (peer->peer_state == DP_PEER_STATE_LOGICAL_DELETE) {
+		if (dp_peer_state_cmp(peer, DP_PEER_STATE_LOGICAL_DELETE)) {
 			dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
 			dp_alert("Peer %pK["QDF_MAC_ADDR_FMT"] logical delete state vid %d",
 				 peer, QDF_MAC_ADDR_REF(peer_mac_addr),
@@ -2171,14 +2171,8 @@ dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id,
 	}
 
 	vdev = peer->vdev;
-	/* cleanup the peer data */
-	dp_peer_cleanup(vdev, peer);
 	DP_UPDATE_STATS(vdev, peer);
 
-	qdf_spin_lock_bh(&soc->inactive_peer_list_lock);
-	TAILQ_INSERT_TAIL(&soc->inactive_peer_list, peer, inactive_list_elem);
-	qdf_spin_unlock_bh(&soc->inactive_peer_list_lock);
-
 	dp_peer_update_state(soc, peer, DP_PEER_STATE_INACTIVE);
 	dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
 	/*

+ 28 - 1
dp/wifi3.0/dp_peer.h

@@ -434,6 +434,28 @@ dp_soc_iterate_peer_lock_safe(struct dp_soc *soc,
 	} while (0)
 #endif
 
+/**
+ * dp_peer_state_cmp() - compare dp peer state
+ *
+ * @peer	: DP peer
+ * @state	: state
+ *
+ * Return: true if state matches with peer state
+ *	   false if it does not match
+ */
+static inline bool
+dp_peer_state_cmp(struct dp_peer *peer,
+		  enum dp_peer_state state)
+{
+	bool is_status_equal = false;
+
+	qdf_spin_lock_bh(&peer->peer_state_lock);
+	is_status_equal = (peer->peer_state == state);
+	qdf_spin_unlock_bh(&peer->peer_state_lock);
+
+	return is_status_equal;
+}
+
 /**
  * dp_peer_update_state() - update dp peer state
  *
@@ -448,7 +470,10 @@ dp_peer_update_state(struct dp_soc *soc,
 		     struct dp_peer *peer,
 		     enum dp_peer_state state)
 {
-	uint8_t peer_state = peer->peer_state;
+	uint8_t peer_state;
+
+	qdf_spin_lock_bh(&peer->peer_state_lock);
+	peer_state = peer->peer_state;
 
 	switch (state) {
 	case DP_PEER_STATE_INIT:
@@ -488,12 +513,14 @@ dp_peer_update_state(struct dp_soc *soc,
 	default:
 		dp_alert("Invalid peer state %u for peer "QDF_MAC_ADDR_FMT,
 			 state, QDF_MAC_ADDR_REF(peer->mac_addr.raw));
+		qdf_spin_unlock_bh(&peer->peer_state_lock);
 		return;
 	}
 	dp_info("Updating peer state from %u to %u mac "QDF_MAC_ADDR_FMT"\n",
 		peer_state, state,
 		QDF_MAC_ADDR_REF(peer->mac_addr.raw));
 	peer->peer_state = state;
+	qdf_spin_unlock_bh(&peer->peer_state_lock);
 }
 
 void dp_print_ast_stats(struct dp_soc *soc);

+ 24 - 26
dp/wifi3.0/dp_types.h

@@ -177,29 +177,29 @@ enum dp_peer_state {
  * enum for modules ids of
  */
 enum dp_mod_id {
-	DP_MOD_ID_TX_COMP,
-	DP_MOD_ID_RX,
-	DP_MOD_ID_HTT_COMP,
-	DP_MOD_ID_RX_ERR,
-	DP_MOD_ID_TX_PPDU_STATS,
-	DP_MOD_ID_RX_PPDU_STATS,
-	DP_MOD_ID_CDP,
-	DP_MOD_ID_GENERIC_STATS,
-	DP_MOD_ID_TX_MULTIPASS,
-	DP_MOD_ID_TX_CAPTURE,
-	DP_MOD_ID_NSS_OFFLOAD,
-	DP_MOD_ID_CONFIG,
-	DP_MOD_ID_HTT,
-	DP_MOD_ID_IPA,
-	DP_MOD_ID_AST,
-	DP_MOD_ID_MCAST2UCAST,
-	DP_MOD_ID_CHILD,
-	DP_MOD_ID_MESH,
-	DP_MOD_ID_TX_EXCEPTION,
-	DP_MOD_ID_TDLS,
-	DP_MOD_ID_MISC,
-	DP_MOD_ID_MSCS,
-	DP_MOD_ID_MAX,
+	DP_MOD_ID_TX_COMP = 0,
+	DP_MOD_ID_RX = 1,
+	DP_MOD_ID_HTT_COMP = 2,
+	DP_MOD_ID_RX_ERR = 3,
+	DP_MOD_ID_TX_PPDU_STATS = 4,
+	DP_MOD_ID_RX_PPDU_STATS = 5,
+	DP_MOD_ID_CDP = 6,
+	DP_MOD_ID_GENERIC_STATS = 7,
+	DP_MOD_ID_TX_MULTIPASS = 8,
+	DP_MOD_ID_TX_CAPTURE = 9,
+	DP_MOD_ID_NSS_OFFLOAD = 10,
+	DP_MOD_ID_CONFIG = 11,
+	DP_MOD_ID_HTT = 12,
+	DP_MOD_ID_IPA = 13,
+	DP_MOD_ID_AST = 14,
+	DP_MOD_ID_MCAST2UCAST = 15,
+	DP_MOD_ID_CHILD = 16,
+	DP_MOD_ID_MESH = 17,
+	DP_MOD_ID_TX_EXCEPTION = 18,
+	DP_MOD_ID_TDLS = 19,
+	DP_MOD_ID_MISC = 20,
+	DP_MOD_ID_MSCS = 21,
+	DP_MOD_ID_MAX = 22,
 };
 
 #define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \
@@ -2291,9 +2291,6 @@ struct dp_vdev {
 	/* Rx Decapsulation type for this VAP */
 	enum htt_cmn_pkt_type rx_decap_type;
 
-	/* BSS peer */
-	struct dp_peer *vap_bss_peer;
-
 	/* WDS enabled */
 	bool wds_enabled;
 
@@ -2736,6 +2733,7 @@ struct dp_peer {
 	qdf_atomic_t mod_refs[DP_MOD_ID_MAX];
 
 	uint8_t peer_state;
+	qdf_spinlock_t peer_state_lock;
 #ifdef WLAN_SUPPORT_MSCS
 	struct dp_peer_mscs_parameter mscs_ipv4_parameter, mscs_ipv6_parameter;
 	bool mscs_active;