Parcourir la source

qcacmn: Take peer ref count and dec it after using

Currently peer reference is used with out taking any ref count.
In parallel context execution on different core peer reference may
be cleaned up in peer unmap event. So take ref count while using
the peer reference and decrement after done with it.

Change-Id: I02ca172cbdc4309fabd3bbbad00940826662bbd3
CRs-Fixed: 2301963
Sravan Kumar Kairam il y a 6 ans
Parent
commit
26d471ec56

+ 21 - 33
dp/wifi3.0/dp_htt.c

@@ -1796,7 +1796,6 @@ static void dp_process_ppdu_stats_user_common_tlv(
 		struct ppdu_info *ppdu_info)
 		struct ppdu_info *ppdu_info)
 {
 {
 	uint16_t peer_id;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
 	uint8_t curr_user_index = 0;
@@ -1816,8 +1815,7 @@ static void dp_process_ppdu_stats_user_common_tlv(
 		ppdu_desc->vdev_id =
 		ppdu_desc->vdev_id =
 			HTT_PPDU_STATS_USER_COMMON_TLV_VAP_ID_GET(*tag_buf);
 			HTT_PPDU_STATS_USER_COMMON_TLV_VAP_ID_GET(*tag_buf);
 	} else {
 	} else {
-		peer = dp_peer_find_by_id(pdev->soc, peer_id);
-		if (!peer)
+		if (!dp_peer_find_by_id_valid(pdev->soc, peer_id))
 			return;
 			return;
 	}
 	}
 
 
@@ -1883,7 +1881,6 @@ static void dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev,
 		dp_get_ppdu_info_user_index(pdev,
 		dp_get_ppdu_info_user_index(pdev,
 					    peer_id, ppdu_info);
 					    peer_id, ppdu_info);
 	ppdu_user_desc = &ppdu_desc->user[curr_user_index];
 	ppdu_user_desc = &ppdu_desc->user[curr_user_index];
-
 	if (peer_id == DP_SCAN_PEER_ID) {
 	if (peer_id == DP_SCAN_PEER_ID) {
 		vdev =
 		vdev =
 		       dp_get_vdev_from_soc_vdev_id_wifi3(pdev->soc,
 		       dp_get_vdev_from_soc_vdev_id_wifi3(pdev->soc,
@@ -1896,6 +1893,7 @@ static void dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev,
 			return;
 			return;
 		qdf_mem_copy(ppdu_user_desc->mac_addr,
 		qdf_mem_copy(ppdu_user_desc->mac_addr,
 			     peer->mac_addr.raw, DP_MAC_ADDR_LEN);
 			     peer->mac_addr.raw, DP_MAC_ADDR_LEN);
+		dp_peer_unref_del_find_by_id(peer);
 	}
 	}
 
 
 	ppdu_user_desc->peer_id = peer_id;
 	ppdu_user_desc->peer_id = peer_id;
@@ -1956,7 +1954,6 @@ static void dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv(
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
 	uint8_t curr_user_index = 0;
 	uint16_t peer_id;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 
 
 	ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf);
 	ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf);
 
 
@@ -1965,9 +1962,7 @@ static void dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv(
 	peer_id =
 	peer_id =
 	HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
 	HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
 
 
-	peer = dp_peer_find_by_id(pdev->soc, peer_id);
-
-	if (!peer)
+	if (!dp_peer_find_by_id_valid(pdev->soc, peer_id))
 		return;
 		return;
 
 
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
@@ -2000,7 +1995,6 @@ static void dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv(
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
 	uint8_t curr_user_index = 0;
 	uint16_t peer_id;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 
 
 	ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf);
 	ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf);
 
 
@@ -2009,9 +2003,7 @@ static void dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv(
 	peer_id =
 	peer_id =
 	HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
 	HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
 
 
-	peer = dp_peer_find_by_id(pdev->soc, peer_id);
-
-	if (!peer)
+	if (!dp_peer_find_by_id_valid(pdev->soc, peer_id))
 		return;
 		return;
 
 
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
@@ -2038,7 +2030,6 @@ static void dp_process_ppdu_stats_user_cmpltn_common_tlv(
 		struct ppdu_info *ppdu_info)
 		struct ppdu_info *ppdu_info)
 {
 {
 	uint16_t peer_id;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
 	uint8_t curr_user_index = 0;
@@ -2050,9 +2041,8 @@ static void dp_process_ppdu_stats_user_cmpltn_common_tlv(
 	tag_buf++;
 	tag_buf++;
 	peer_id =
 	peer_id =
 		HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SW_PEER_ID_GET(*tag_buf);
 		HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SW_PEER_ID_GET(*tag_buf);
-	peer = dp_peer_find_by_id(pdev->soc, peer_id);
 
 
-	if (!peer)
+	if (!dp_peer_find_by_id_valid(pdev->soc, peer_id))
 		return;
 		return;
 
 
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
@@ -2115,7 +2105,6 @@ static void dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv(
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	uint8_t curr_user_index = 0;
 	uint8_t curr_user_index = 0;
 	uint16_t peer_id;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 
 
 	ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf);
 	ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf);
 
 
@@ -2124,9 +2113,7 @@ static void dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv(
 	peer_id =
 	peer_id =
 	HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
 	HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
 
 
-	peer = dp_peer_find_by_id(pdev->soc, peer_id);
-
-	if (!peer)
+	if (!dp_peer_find_by_id_valid(pdev->soc, peer_id))
 		return;
 		return;
 
 
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
@@ -2158,7 +2145,6 @@ static void dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv(
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	uint8_t curr_user_index = 0;
 	uint8_t curr_user_index = 0;
 	uint16_t peer_id;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 
 
 	ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf);
 	ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf);
 
 
@@ -2167,9 +2153,7 @@ static void dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv(
 	peer_id =
 	peer_id =
 	HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
 	HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
 
 
-	peer = dp_peer_find_by_id(pdev->soc, peer_id);
-
-	if (!peer)
+	if (!dp_peer_find_by_id_valid(pdev->soc, peer_id))
 		return;
 		return;
 
 
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
@@ -2196,7 +2180,6 @@ static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv(
 		struct ppdu_info *ppdu_info)
 		struct ppdu_info *ppdu_info)
 {
 {
 	uint16_t peer_id;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
 	uint8_t curr_user_index = 0;
@@ -2207,10 +2190,7 @@ static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv(
 	peer_id =
 	peer_id =
 	HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_SW_PEER_ID_GET(*tag_buf);
 	HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_SW_PEER_ID_GET(*tag_buf);
 
 
-
-	peer = dp_peer_find_by_id(pdev->soc, peer_id);
-
-	if (!peer)
+	if (!dp_peer_find_by_id_valid(pdev->soc, peer_id))
 		return;
 		return;
 
 
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
 	curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info);
@@ -2248,7 +2228,6 @@ static void dp_process_ppdu_stats_user_common_array_tlv(
 		struct ppdu_info *ppdu_info)
 		struct ppdu_info *ppdu_info)
 {
 {
 	uint32_t peer_id;
 	uint32_t peer_id;
-	struct dp_peer *peer;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
 	uint8_t curr_user_index = 0;
@@ -2262,9 +2241,7 @@ static void dp_process_ppdu_stats_user_common_array_tlv(
 	peer_id =
 	peer_id =
 		HTT_PPDU_STATS_ARRAY_ITEM_TLV_PEERID_GET(*tag_buf);
 		HTT_PPDU_STATS_ARRAY_ITEM_TLV_PEERID_GET(*tag_buf);
 
 
-	peer = dp_peer_find_by_id(pdev->soc, peer_id);
-
-	if (!peer) {
+	if (!dp_peer_find_by_id_valid(pdev->soc, peer_id)) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"Invalid peer");
 			"Invalid peer");
 		return;
 		return;
@@ -2325,6 +2302,8 @@ static void dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev,
 		DP_STATS_INC(peer, tx.excess_retries_per_ac[TID_TO_WME_AC(tid)],
 		DP_STATS_INC(peer, tx.excess_retries_per_ac[TID_TO_WME_AC(tid)],
 					num_msdu);
 					num_msdu);
 	}
 	}
+
+	dp_peer_unref_del_find_by_id(peer);
 }
 }
 
 
 /*
 /*
@@ -2470,7 +2449,7 @@ static void dp_process_ppdu_tag(struct dp_pdev *pdev, uint32_t *tag_buf,
  */
  */
 static
 static
 void dp_ppdu_desc_deliver(struct dp_pdev *pdev,
 void dp_ppdu_desc_deliver(struct dp_pdev *pdev,
-			      struct ppdu_info *ppdu_info)
+			  struct ppdu_info *ppdu_info)
 {
 {
 	struct cdp_tx_completion_ppdu *ppdu_desc = NULL;
 	struct cdp_tx_completion_ppdu *ppdu_desc = NULL;
 	struct dp_peer *peer = NULL;
 	struct dp_peer *peer = NULL;
@@ -2502,6 +2481,8 @@ void dp_ppdu_desc_deliver(struct dp_pdev *pdev,
 			dp_tx_stats_update(pdev->soc, peer,
 			dp_tx_stats_update(pdev->soc, peer,
 					&ppdu_desc->user[i],
 					&ppdu_desc->user[i],
 					ppdu_desc->ack_rssi);
 					ppdu_desc->ack_rssi);
+
+			dp_peer_unref_del_find_by_id(peer);
 		}
 		}
 
 
 		dp_tx_rate_stats_update(peer, &ppdu_desc->user[i]);
 		dp_tx_rate_stats_update(peer, &ppdu_desc->user[i]);
@@ -3075,6 +3056,13 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
 			if (peer) {
 			if (peer) {
 				status = dp_addba_requestprocess_wifi3(peer,
 				status = dp_addba_requestprocess_wifi3(peer,
 						0, tid, 0, win_sz + 1, 0xffff);
 						0, tid, 0, win_sz + 1, 0xffff);
+
+				/*
+				 * If PEER_LOCK_REF_PROTECT enbled dec ref
+				 * which is inc by dp_peer_find_by_id
+				 */
+				dp_peer_unref_del_find_by_id(peer);
+
 				QDF_TRACE(QDF_MODULE_ID_TXRX,
 				QDF_TRACE(QDF_MODULE_ID_TXRX,
 					QDF_TRACE_LEVEL_INFO,
 					QDF_TRACE_LEVEL_INFO,
 					FL("PeerID %d BAW %d TID %d stat %d"),
 					FL("PeerID %d BAW %d TID %d stat %d"),

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

@@ -853,4 +853,23 @@ void dp_tx_dump_flow_pool_info(void *soc);
 int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool,
 int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool,
 	bool force);
 	bool force);
 #endif /* QCA_LL_TX_FLOW_CONTROL_V2 */
 #endif /* QCA_LL_TX_FLOW_CONTROL_V2 */
+
+#ifdef PEER_PROTECTED_ACCESS
+/**
+ * dp_peer_unref_del_find_by_id() - dec ref and del peer if ref count is
+ *                                  taken by dp_peer_find_by_id
+ * @peer: peer context
+ *
+ * Return: none
+ */
+static inline void dp_peer_unref_del_find_by_id(struct dp_peer *peer)
+{
+	dp_peer_unref_delete(peer);
+}
+#else
+static inline void dp_peer_unref_del_find_by_id(struct dp_peer *peer)
+{
+}
+#endif
+
 #endif /* #ifndef _DP_INTERNAL_H_ */
 #endif /* #ifndef _DP_INTERNAL_H_ */

+ 5 - 3
dp/wifi3.0/dp_main.c

@@ -4973,9 +4973,11 @@ static void dp_get_peer_mac_from_peer_id(struct cdp_pdev *pdev_handle,
 
 
 	if (pdev && peer_mac) {
 	if (pdev && peer_mac) {
 		peer = dp_peer_find_by_id(pdev->soc, (uint16_t)peer_id);
 		peer = dp_peer_find_by_id(pdev->soc, (uint16_t)peer_id);
-		if (peer && peer->mac_addr.raw) {
-			qdf_mem_copy(peer_mac, peer->mac_addr.raw,
-					DP_MAC_ADDR_LEN);
+		if (peer) {
+			if (peer->mac_addr.raw)
+				qdf_mem_copy(peer_mac, peer->mac_addr.raw,
+					     DP_MAC_ADDR_LEN);
+			dp_peer_unref_del_find_by_id(peer);
 		}
 		}
 	}
 	}
 }
 }

+ 25 - 1
dp/wifi3.0/dp_peer.c

@@ -2400,6 +2400,8 @@ dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id,
 	 * all security types and last pn for WAPI) once REO command API
 	 * all security types and last pn for WAPI) once REO command API
 	 * is available
 	 * is available
 	 */
 	 */
+
+	dp_peer_unref_del_find_by_id(peer);
 }
 }
 
 
 #ifndef CONFIG_WIN
 #ifndef CONFIG_WIN
@@ -2768,6 +2770,7 @@ uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
 {
 {
 	struct dp_soc *soc = (struct dp_soc *)soc_handle;
 	struct dp_soc *soc = (struct dp_soc *)soc_handle;
 	struct dp_peer *peer;
 	struct dp_peer *peer;
+	uint8_t vdev_id;
 
 
 	peer = dp_peer_find_by_id(soc, peer_id);
 	peer = dp_peer_find_by_id(soc, peer_id);
 
 
@@ -2781,7 +2784,11 @@ uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
 	}
 	}
 
 
 	qdf_mem_copy(peer_mac, peer->mac_addr.raw, 6);
 	qdf_mem_copy(peer_mac, peer->mac_addr.raw, 6);
-	return peer->vdev->vdev_id;
+	vdev_id = peer->vdev->vdev_id;
+
+	dp_peer_unref_del_find_by_id(peer);
+
+	return vdev_id;
 }
 }
 
 
 /**
 /**
@@ -2850,3 +2857,20 @@ void dp_set_michael_key(struct cdp_peer *peer_handle,
 	qdf_mem_copy(&peer->security[sec_index].michael_key[0],
 	qdf_mem_copy(&peer->security[sec_index].michael_key[0],
 		     key, IEEE80211_WEP_MICLEN);
 		     key, IEEE80211_WEP_MICLEN);
 }
 }
+
+bool dp_peer_find_by_id_valid(struct dp_soc *soc, uint16_t peer_id)
+{
+	struct dp_peer *peer = dp_peer_find_by_id(soc, peer_id);
+
+	if (peer) {
+		/*
+		 * Decrement the peer ref which is taken as part of
+		 * dp_peer_find_by_id if PEER_LOCK_REF_PROTECT is enabled
+		 */
+		dp_peer_unref_del_find_by_id(peer);
+
+		return true;
+	}
+
+	return false;
+}

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

@@ -44,6 +44,7 @@ __dp_peer_find_by_id(struct dp_soc *soc,
 	return peer;
 	return peer;
 }
 }
 
 
+#ifdef PEER_PROTECTED_ACCESS
 /**
 /**
  * dp_peer_find_by_id() - Returns peer object given the peer id
  * dp_peer_find_by_id() - Returns peer object given the peer id
  *                        if delete_in_progress in not set for peer
  *                        if delete_in_progress in not set for peer
@@ -53,6 +54,24 @@ __dp_peer_find_by_id(struct dp_soc *soc,
  *
  *
  * Return: struct dp_peer*: Pointer to DP peer object
  * Return: struct dp_peer*: Pointer to DP peer object
  */
  */
+static inline
+struct dp_peer *dp_peer_find_by_id(struct dp_soc *soc,
+				   uint16_t peer_id)
+{
+	struct dp_peer *peer;
+
+	qdf_spin_lock_bh(&soc->peer_ref_mutex);
+	peer = __dp_peer_find_by_id(soc, peer_id);
+	if (!peer || (peer && peer->delete_in_progress)) {
+		qdf_spin_unlock_bh(&soc->peer_ref_mutex);
+		return NULL;
+	}
+	qdf_atomic_inc(&peer->ref_cnt);
+	qdf_spin_unlock_bh(&soc->peer_ref_mutex);
+
+	return peer;
+}
+#else
 static inline struct dp_peer *
 static inline struct dp_peer *
 dp_peer_find_by_id(struct dp_soc *soc,
 dp_peer_find_by_id(struct dp_soc *soc,
 		   uint16_t peer_id)
 		   uint16_t peer_id)
@@ -60,13 +79,13 @@ dp_peer_find_by_id(struct dp_soc *soc,
 	struct dp_peer *peer;
 	struct dp_peer *peer;
 
 
 	peer = __dp_peer_find_by_id (soc, peer_id);
 	peer = __dp_peer_find_by_id (soc, peer_id);
-
 	if (peer && peer->delete_in_progress) {
 	if (peer && peer->delete_in_progress) {
 		return NULL;
 		return NULL;
 	}
 	}
 
 
 	return peer;
 	return peer;
 }
 }
+#endif /* PEER_LOCK_REF_PROTECT */
 
 
 void dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id,
 void dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id,
 			    uint16_t hw_peer_id, uint8_t vdev_id,
 			    uint16_t hw_peer_id, uint8_t vdev_id,
@@ -163,4 +182,13 @@ dp_get_vdev_from_soc_vdev_id_wifi3(struct dp_soc *soc,
 	return NULL;
 	return NULL;
 
 
 }
 }
+
+/*
+ * dp_peer_find_by_id_exist - check if peer exists for given id
+ * @soc: core DP soc context
+ * @peer_id: peer id from peer object can be retrieved
+ *
+ * Return: true if peer exists of false otherwise
+ */
+bool dp_peer_find_by_id_valid(struct dp_soc *soc, uint16_t peer_id);
 #endif /* _DP_PEER_H_ */
 #endif /* _DP_PEER_H_ */

+ 7 - 0
dp/wifi3.0/dp_rx.c

@@ -1527,6 +1527,7 @@ done:
 			qdf_nbuf_free(nbuf);
 			qdf_nbuf_free(nbuf);
 			nbuf = next;
 			nbuf = next;
 			DP_STATS_INC(soc, rx.err.invalid_vdev, 1);
 			DP_STATS_INC(soc, rx.err.invalid_vdev, 1);
+			dp_peer_unref_del_find_by_id(peer);
 			continue;
 			continue;
 		}
 		}
 
 
@@ -1590,6 +1591,7 @@ done:
 			qdf_nbuf_free(nbuf);
 			qdf_nbuf_free(nbuf);
 			/* Statistics */
 			/* Statistics */
 			nbuf = next;
 			nbuf = next;
+			dp_peer_unref_del_find_by_id(peer);
 			continue;
 			continue;
 		}
 		}
 
 
@@ -1603,6 +1605,7 @@ done:
 			qdf_nbuf_free(nbuf);
 			qdf_nbuf_free(nbuf);
 			/* Statistics */
 			/* Statistics */
 			nbuf = next;
 			nbuf = next;
+			dp_peer_unref_del_find_by_id(peer);
 			continue;
 			continue;
 		}
 		}
 
 
@@ -1612,6 +1615,7 @@ done:
 			DP_STATS_INC(peer, rx.nawds_mcast_drop, 1);
 			DP_STATS_INC(peer, rx.nawds_mcast_drop, 1);
 			qdf_nbuf_free(nbuf);
 			qdf_nbuf_free(nbuf);
 			nbuf = next;
 			nbuf = next;
+			dp_peer_unref_del_find_by_id(peer);
 			continue;
 			continue;
 		}
 		}
 
 
@@ -1643,6 +1647,7 @@ done:
 
 
 				qdf_nbuf_free(nbuf);
 				qdf_nbuf_free(nbuf);
 				nbuf = next;
 				nbuf = next;
+				dp_peer_unref_del_find_by_id(peer);
 				continue;
 				continue;
 			}
 			}
 			dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer);
 			dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer);
@@ -1673,6 +1678,7 @@ done:
 							rx_tlv_hdr,
 							rx_tlv_hdr,
 							nbuf)) {
 							nbuf)) {
 					nbuf = next;
 					nbuf = next;
+					dp_peer_unref_del_find_by_id(peer);
 					continue; /* Get next desc */
 					continue; /* Get next desc */
 				}
 				}
 		}
 		}
@@ -1686,6 +1692,7 @@ done:
 				qdf_nbuf_len(nbuf));
 				qdf_nbuf_len(nbuf));
 
 
 		nbuf = next;
 		nbuf = next;
+		dp_peer_unref_del_find_by_id(peer);
 	}
 	}
 
 
 	if (deliver_list_head)
 	if (deliver_list_head)

+ 2 - 1
dp/wifi3.0/dp_rx.h

@@ -517,7 +517,8 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc,
 uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf);
 uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf);
 void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc,
 void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc,
 		qdf_nbuf_t mpdu, bool mpdu_done);
 		qdf_nbuf_t mpdu, bool mpdu_done);
-void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr);
+void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf,
+			     uint8_t *rx_tlv_hdr, struct dp_peer *peer);
 
 
 #define DP_RX_LIST_APPEND(head, tail, elem) \
 #define DP_RX_LIST_APPEND(head, tail, elem) \
 	do {                                                          \
 	do {                                                          \

+ 6 - 0
dp/wifi3.0/dp_rx_defrag.c

@@ -1525,6 +1525,7 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
 			now_ms + pdev->soc->rx.defrag.timeout_ms;
 			now_ms + pdev->soc->rx.defrag.timeout_ms;
 
 
 		dp_rx_defrag_waitlist_add(peer, tid);
 		dp_rx_defrag_waitlist_add(peer, tid);
+		dp_peer_unref_del_find_by_id(peer);
 
 
 		return QDF_STATUS_SUCCESS;
 		return QDF_STATUS_SUCCESS;
 	}
 	}
@@ -1569,9 +1570,14 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
 	}
 	}
 
 
 	dp_rx_defrag_cleanup(peer, tid);
 	dp_rx_defrag_cleanup(peer, tid);
+
+	dp_peer_unref_del_find_by_id(peer);
+
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 
 
 end:
 end:
+	dp_peer_unref_del_find_by_id(peer);
+
 	return QDF_STATUS_E_DEFRAG_ERROR;
 	return QDF_STATUS_E_DEFRAG_ERROR;
 }
 }
 
 

+ 57 - 57
dp/wifi3.0/dp_rx_err.c

@@ -358,6 +358,7 @@ dp_rx_pn_error_handle(struct dp_soc *soc, void *ring_desc,
 			peer->mac_addr.raw[2], peer->mac_addr.raw[3],
 			peer->mac_addr.raw[2], peer->mac_addr.raw[3],
 			peer->mac_addr.raw[4], peer->mac_addr.raw[5]);
 			peer->mac_addr.raw[4], peer->mac_addr.raw[5]);
 
 
+		dp_peer_unref_del_find_by_id(peer);
 	}
 	}
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 		"Packet received with PN error");
 		"Packet received with PN error");
@@ -547,6 +548,7 @@ free_nbuf:
  * @nbuf: buffer pointer
  * @nbuf: buffer pointer
  * @rx_tlv_hdr: start of rx tlv header
  * @rx_tlv_hdr: start of rx tlv header
  * @pool_id: mac id
  * @pool_id: mac id
+ * @peer: peer handle
  *
  *
  * This function handles NULL queue descriptor violations arising out
  * This function handles NULL queue descriptor violations arising out
  * a missing REO queue for a given peer or a given TID. This typically
  * a missing REO queue for a given peer or a given TID. This typically
@@ -558,16 +560,13 @@ free_nbuf:
  *
  *
  */
  */
 static void
 static void
-dp_rx_null_q_desc_handle(struct dp_soc *soc,
-			qdf_nbuf_t nbuf,
-			uint8_t *rx_tlv_hdr,
-			uint8_t pool_id)
+dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf,
+			 uint8_t *rx_tlv_hdr, uint8_t pool_id,
+			 struct dp_peer *peer)
 {
 {
 	uint32_t pkt_len, l2_hdr_offset;
 	uint32_t pkt_len, l2_hdr_offset;
 	uint16_t msdu_len;
 	uint16_t msdu_len;
 	struct dp_vdev *vdev;
 	struct dp_vdev *vdev;
-	uint16_t peer_id = 0xFFFF;
-	struct dp_peer *peer = NULL;
 	uint8_t tid;
 	uint8_t tid;
 	struct ether_header *eh;
 	struct ether_header *eh;
 
 
@@ -602,9 +601,6 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc,
 		qdf_assert(0);
 		qdf_assert(0);
 	}
 	}
 
 
-	peer_id = hal_rx_mpdu_start_sw_peer_id_get(rx_tlv_hdr);
-	peer = dp_peer_find_by_id(soc, peer_id);
-
 	if (!peer) {
 	if (!peer) {
 		bool mpdu_done = false;
 		bool mpdu_done = false;
 		struct dp_pdev *pdev = soc->pdev_list[pool_id];
 		struct dp_pdev *pdev = soc->pdev_list[pool_id];
@@ -697,8 +693,9 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc,
 
 
 #ifdef QCA_WIFI_NAPIER_EMULATION /* Debug code, remove later */
 #ifdef QCA_WIFI_NAPIER_EMULATION /* Debug code, remove later */
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-			 "%s: p_id %d msdu_len %d hdr_off %d",
-			 __func__, peer_id, msdu_len, l2_hdr_offset);
+		  "%s: mac_add:%pM msdu_len %d hdr_off %d",
+		  __func__, peer->mac_addr.raw, msdu_len,
+		  l2_hdr_offset);
 
 
 	print_hex_dump(KERN_ERR, "\t Pkt Data:", DUMP_PREFIX_NONE, 32, 4,
 	print_hex_dump(KERN_ERR, "\t Pkt Data:", DUMP_PREFIX_NONE, 32, 4,
 					qdf_nbuf_data(nbuf), 128, false);
 					qdf_nbuf_data(nbuf), 128, false);
@@ -748,24 +745,21 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc,
 }
 }
 
 
 /**
 /**
-* dp_rx_err_deliver() - Function to deliver error frames to OS
-*
-* @soc: core DP main context
-* @rx_desc : pointer to the sw rx descriptor
-* @head: pointer to head of rx descriptors to be added to free list
-* @tail: pointer to tail of rx descriptors to be added to free list
-* quota: upper limit of descriptors that can be reaped
-*
-* Return: uint32_t: No. of Rx buffers reaped
-*/
+ * dp_rx_err_deliver() - Function to deliver error frames to OS
+ * @soc: core DP main context
+ * @nbuf: buffer pointer
+ * @rx_tlv_hdr: start of rx tlv header
+ * @peer: peer reference
+ *
+ * Return: None
+ */
 static void
 static void
-dp_rx_err_deliver(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr)
+dp_rx_err_deliver(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
+		  struct dp_peer *peer)
 {
 {
 	uint32_t pkt_len, l2_hdr_offset;
 	uint32_t pkt_len, l2_hdr_offset;
 	uint16_t msdu_len;
 	uint16_t msdu_len;
 	struct dp_vdev *vdev;
 	struct dp_vdev *vdev;
-	uint16_t peer_id = 0xFFFF;
-	struct dp_peer *peer = NULL;
 	struct ether_header *eh;
 	struct ether_header *eh;
 	bool isBroadcast;
 	bool isBroadcast;
 
 
@@ -783,9 +777,6 @@ dp_rx_err_deliver(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr)
 		qdf_assert(0);
 		qdf_assert(0);
 	}
 	}
 
 
-	peer_id = hal_rx_mpdu_start_sw_peer_id_get(rx_tlv_hdr);
-	peer = dp_peer_find_by_id(soc, peer_id);
-
 	l2_hdr_offset = hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr);
 	l2_hdr_offset = hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr);
 	msdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr);
 	msdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr);
 	pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN;
 	pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN;
@@ -867,25 +858,22 @@ dp_rx_err_deliver(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr)
 
 
 /**
 /**
  * dp_rx_process_mic_error(): Function to pass mic error indication to umac
  * dp_rx_process_mic_error(): Function to pass mic error indication to umac
- * @soc: DP SOC handle
- * @rx_desc : pointer to the sw rx descriptor
- * @head: pointer to head of rx descriptors to be added to free list
- * @tail: pointer to tail of rx descriptors to be added to free list
+ * @soc: core DP main context
+ * @nbuf: buffer pointer
+ * @rx_tlv_hdr: start of rx tlv header
+ * @peer: peer handle
  *
  *
  * return: void
  * return: void
  */
  */
-void
-dp_rx_process_mic_error(struct dp_soc *soc,
-			qdf_nbuf_t nbuf,
-			uint8_t *rx_tlv_hdr)
+void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf,
+			     uint8_t *rx_tlv_hdr, struct dp_peer *peer)
 {
 {
 	struct dp_vdev *vdev = NULL;
 	struct dp_vdev *vdev = NULL;
 	struct dp_pdev *pdev = NULL;
 	struct dp_pdev *pdev = NULL;
 	struct ol_if_ops *tops = NULL;
 	struct ol_if_ops *tops = NULL;
 	struct ieee80211_frame *wh;
 	struct ieee80211_frame *wh;
 	uint8_t *rx_pkt_hdr;
 	uint8_t *rx_pkt_hdr;
-	struct dp_peer *peer;
-	uint16_t peer_id, rx_seq, fragno;
+	uint16_t rx_seq, fragno;
 	unsigned int tid;
 	unsigned int tid;
 	QDF_STATUS status;
 	QDF_STATUS status;
 
 
@@ -895,11 +883,9 @@ dp_rx_process_mic_error(struct dp_soc *soc,
 	rx_pkt_hdr = hal_rx_pkt_hdr_get(qdf_nbuf_data(nbuf));
 	rx_pkt_hdr = hal_rx_pkt_hdr_get(qdf_nbuf_data(nbuf));
 	wh = (struct ieee80211_frame *)rx_pkt_hdr;
 	wh = (struct ieee80211_frame *)rx_pkt_hdr;
 
 
-	peer_id = hal_rx_mpdu_start_sw_peer_id_get(rx_tlv_hdr);
-	peer = dp_peer_find_by_id(soc, peer_id);
 	if (!peer) {
 	if (!peer) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-				"peer not found");
+			  "peer not found");
 		goto fail;
 		goto fail;
 	}
 	}
 
 
@@ -1134,7 +1120,6 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
 	qdf_nbuf_t nbuf, next;
 	qdf_nbuf_t nbuf, next;
 	struct hal_wbm_err_desc_info wbm_err_info = { 0 };
 	struct hal_wbm_err_desc_info wbm_err_info = { 0 };
 	uint8_t pool_id;
 	uint8_t pool_id;
-	uint16_t peer_id = 0xFFFF;
 	uint8_t tid = 0;
 	uint8_t tid = 0;
 
 
 	/* Debug -- Remove later */
 	/* Debug -- Remove later */
@@ -1236,7 +1221,14 @@ done:
 
 
 	nbuf = nbuf_head;
 	nbuf = nbuf_head;
 	while (nbuf) {
 	while (nbuf) {
+		struct dp_peer *peer;
+		uint16_t peer_id;
+
 		rx_tlv_hdr = qdf_nbuf_data(nbuf);
 		rx_tlv_hdr = qdf_nbuf_data(nbuf);
+
+		peer_id = hal_rx_mpdu_start_sw_peer_id_get(rx_tlv_hdr);
+		peer = dp_peer_find_by_id(soc, peer_id);
+
 		/*
 		/*
 		 * retrieve the wbm desc info from nbuf TLV, so we can
 		 * retrieve the wbm desc info from nbuf TLV, so we can
 		 * handle error cases appropriately
 		 * handle error cases appropriately
@@ -1265,11 +1257,13 @@ done:
 					QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_DP,
 					QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_DP,
 						"Got pkt with REO ERROR: %d",
 						"Got pkt with REO ERROR: %d",
 						wbm_err_info.reo_err_code);
 						wbm_err_info.reo_err_code);
-					dp_rx_null_q_desc_handle(soc,
-								nbuf,
-								rx_tlv_hdr,
-								pool_id);
+					dp_rx_null_q_desc_handle(soc, nbuf,
+								 rx_tlv_hdr,
+								 pool_id, peer);
 					nbuf = next;
 					nbuf = next;
+					if (peer)
+						dp_peer_unref_del_find_by_id(
+									peer);
 					continue;
 					continue;
 				/* TODO */
 				/* TODO */
 				/* Add per error code accounting */
 				/* Add per error code accounting */
@@ -1288,6 +1282,9 @@ done:
 					dp_2k_jump_handle(soc, nbuf, rx_tlv_hdr,
 					dp_2k_jump_handle(soc, nbuf, rx_tlv_hdr,
 							  peer_id, tid);
 							  peer_id, tid);
 					nbuf = next;
 					nbuf = next;
+					if (peer)
+						dp_peer_unref_del_find_by_id(
+									peer);
 					continue;
 					continue;
 				default:
 				default:
 					QDF_TRACE(QDF_MODULE_ID_DP,
 					QDF_TRACE(QDF_MODULE_ID_DP,
@@ -1300,30 +1297,30 @@ done:
 					HAL_RX_WBM_ERR_SRC_RXDMA) {
 					HAL_RX_WBM_ERR_SRC_RXDMA) {
 			if (wbm_err_info.rxdma_psh_rsn
 			if (wbm_err_info.rxdma_psh_rsn
 					== HAL_RX_WBM_RXDMA_PSH_RSN_ERROR) {
 					== HAL_RX_WBM_RXDMA_PSH_RSN_ERROR) {
-				struct dp_peer *peer = NULL;
-				uint16_t peer_id = 0xFFFF;
-
 				DP_STATS_INC(soc,
 				DP_STATS_INC(soc,
 					rx.err.rxdma_error
 					rx.err.rxdma_error
 					[wbm_err_info.rxdma_err_code], 1);
 					[wbm_err_info.rxdma_err_code], 1);
-				peer_id = hal_rx_mpdu_start_sw_peer_id_get(rx_tlv_hdr);
-				peer = dp_peer_find_by_id(soc, peer_id);
 
 
 				switch (wbm_err_info.rxdma_err_code) {
 				switch (wbm_err_info.rxdma_err_code) {
 				case HAL_RXDMA_ERR_UNENCRYPTED:
 				case HAL_RXDMA_ERR_UNENCRYPTED:
-					dp_rx_err_deliver(soc,
-							nbuf,
-							rx_tlv_hdr);
+					dp_rx_err_deliver(soc, nbuf,
+							  rx_tlv_hdr, peer);
 					nbuf = next;
 					nbuf = next;
+					if (peer)
+						dp_peer_unref_del_find_by_id(
+									peer);
 					continue;
 					continue;
 
 
 				case HAL_RXDMA_ERR_TKIP_MIC:
 				case HAL_RXDMA_ERR_TKIP_MIC:
-					dp_rx_process_mic_error(soc,
-								nbuf,
-								rx_tlv_hdr);
+					dp_rx_process_mic_error(soc, nbuf,
+								rx_tlv_hdr,
+								peer);
 					nbuf = next;
 					nbuf = next;
-					if (peer)
+					if (peer) {
 						DP_STATS_INC(peer, rx.err.mic_err, 1);
 						DP_STATS_INC(peer, rx.err.mic_err, 1);
+						dp_peer_unref_del_find_by_id(
+									peer);
+					}
 					continue;
 					continue;
 
 
 				case HAL_RXDMA_ERR_DECRYPT:
 				case HAL_RXDMA_ERR_DECRYPT:
@@ -1347,6 +1344,9 @@ done:
 			qdf_assert(0);
 			qdf_assert(0);
 		}
 		}
 
 
+		if (peer)
+			dp_peer_unref_del_find_by_id(peer);
+
 		hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr,
 		hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr,
 				     QDF_TRACE_LEVEL_DEBUG);
 				     QDF_TRACE_LEVEL_DEBUG);
 		qdf_nbuf_free(nbuf);
 		qdf_nbuf_free(nbuf);

+ 8 - 5
dp/wifi3.0/dp_rx_mon_status.c

@@ -408,12 +408,15 @@ dp_rx_handle_ppdu_stats(struct dp_soc *soc, struct dp_pdev *pdev,
 				sizeof(struct cdp_rx_indication_ppdu));
 				sizeof(struct cdp_rx_indication_ppdu));
 		cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)ppdu_nbuf->data;
 		cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)ppdu_nbuf->data;
 
 
-		peer = dp_peer_find_by_id(soc, cdp_rx_ppdu->peer_id);
-		if (peer && cdp_rx_ppdu->peer_id != HTT_INVALID_PEER) {
-			dp_rx_stats_update(soc, peer, cdp_rx_ppdu);
-			dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC, soc,
-					ppdu_nbuf, cdp_rx_ppdu->peer_id,
+		if (cdp_rx_ppdu->peer_id != HTT_INVALID_PEER) {
+			peer = dp_peer_find_by_id(soc, cdp_rx_ppdu->peer_id);
+			if (peer) {
+				dp_rx_stats_update(soc, peer, cdp_rx_ppdu);
+				dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC,
+					soc, ppdu_nbuf, cdp_rx_ppdu->peer_id,
 					WDI_NO_VAL, pdev->pdev_id);
 					WDI_NO_VAL, pdev->pdev_id);
+				dp_peer_unref_del_find_by_id(peer);
+			}
 		} else if (pdev->mcopy_mode) {
 		} else if (pdev->mcopy_mode) {
 			dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC, soc,
 			dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC, soc,
 					ppdu_nbuf, HTT_INVALID_PEER,
 					ppdu_nbuf, HTT_INVALID_PEER,

+ 26 - 21
dp/wifi3.0/dp_tx.c

@@ -2312,8 +2312,9 @@ static void dp_tx_inspect_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
 #ifdef FEATURE_PERPKT_INFO
 #ifdef FEATURE_PERPKT_INFO
 /**
 /**
  * dp_get_completion_indication_for_stack() - send completion to stack
  * dp_get_completion_indication_for_stack() - send completion to stack
- * @soc :  dp_soc handle
- * @pdev:  dp_pdev handle
+ * @soc : dp_soc handle
+ * @pdev: dp_pdev handle
+ * @peer: dp peer handle
  * @peer_id: peer_id of the peer for which completion came
  * @peer_id: peer_id of the peer for which completion came
  * @ppdu_id: ppdu_id
  * @ppdu_id: ppdu_id
  * @first_msdu: first msdu
  * @first_msdu: first msdu
@@ -2324,20 +2325,18 @@ static void dp_tx_inspect_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
  * send to stack for free or not
  * send to stack for free or not
 */
 */
 QDF_STATUS
 QDF_STATUS
-dp_get_completion_indication_for_stack(struct dp_soc *soc,  struct dp_pdev *pdev,
-		      uint16_t peer_id, uint32_t ppdu_id, uint8_t first_msdu,
-		      uint8_t last_msdu, qdf_nbuf_t netbuf)
+dp_get_completion_indication_for_stack(struct dp_soc *soc,
+				       struct dp_pdev *pdev,
+				       struct dp_peer *peer, uint16_t peer_id,
+				       uint32_t ppdu_id, uint8_t first_msdu,
+				       uint8_t last_msdu, qdf_nbuf_t netbuf)
 {
 {
 	struct tx_capture_hdr *ppdu_hdr;
 	struct tx_capture_hdr *ppdu_hdr;
-	struct dp_peer *peer = NULL;
 	struct ether_header *eh;
 	struct ether_header *eh;
 
 
 	if (qdf_unlikely(!pdev->tx_sniffer_enable && !pdev->mcopy_mode))
 	if (qdf_unlikely(!pdev->tx_sniffer_enable && !pdev->mcopy_mode))
 		return QDF_STATUS_E_NOSUPPORT;
 		return QDF_STATUS_E_NOSUPPORT;
 
 
-	peer = (peer_id == HTT_INVALID_PEER) ? NULL :
-			dp_peer_find_by_id(soc, peer_id);
-
 	if (!peer) {
 	if (!peer) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				FL("Peer Invalid"));
 				FL("Peer Invalid"));
@@ -2402,9 +2401,11 @@ void  dp_send_completion_to_stack(struct dp_soc *soc,  struct dp_pdev *pdev,
 }
 }
 #else
 #else
 static QDF_STATUS
 static QDF_STATUS
-dp_get_completion_indication_for_stack(struct dp_soc *soc,  struct dp_pdev *pdev,
-		      uint16_t peer_id, uint32_t ppdu_id, uint8_t first_msdu,
-		      uint8_t last_msdu, qdf_nbuf_t netbuf)
+dp_get_completion_indication_for_stack(struct dp_soc *soc,
+				       struct dp_pdev *pdev,
+				       struct dp_peer *peer, uint16_t peer_id,
+				       uint32_t ppdu_id, uint8_t first_msdu,
+				       uint8_t last_msdu, qdf_nbuf_t netbuf)
 {
 {
 	return QDF_STATUS_E_NOSUPPORT;
 	return QDF_STATUS_E_NOSUPPORT;
 }
 }
@@ -2863,16 +2864,17 @@ static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev,
  * dp_tx_comp_process_tx_status() - Parse and Dump Tx completion status info
  * dp_tx_comp_process_tx_status() - Parse and Dump Tx completion status info
  * @tx_desc: software descriptor head pointer
  * @tx_desc: software descriptor head pointer
  * @length: packet length
  * @length: packet length
+ * @peer: peer handle
  *
  *
  * Return: none
  * Return: none
  */
  */
-static inline void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc,
-		uint32_t length)
+static inline
+void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc,
+				  uint32_t length, struct dp_peer *peer)
 {
 {
 	struct hal_tx_completion_status ts = {0};
 	struct hal_tx_completion_status ts = {0};
 	struct dp_soc *soc = NULL;
 	struct dp_soc *soc = NULL;
 	struct dp_vdev *vdev = tx_desc->vdev;
 	struct dp_vdev *vdev = tx_desc->vdev;
-	struct dp_peer *peer = NULL;
 	struct ether_header *eh =
 	struct ether_header *eh =
 		(struct ether_header *)qdf_nbuf_data(tx_desc->nbuf);
 		(struct ether_header *)qdf_nbuf_data(tx_desc->nbuf);
 
 
@@ -2925,7 +2927,6 @@ static inline void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc,
 		dp_tx_comp_fill_tx_completion_stats(tx_desc, &ts);
 		dp_tx_comp_fill_tx_completion_stats(tx_desc, &ts);
 
 
 	/* Update peer level stats */
 	/* Update peer level stats */
-	peer = dp_peer_find_by_id(soc, ts.peer_id);
 	if (!peer) {
 	if (!peer) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
 				"invalid peer");
 				"invalid peer");
@@ -2979,7 +2980,7 @@ static void dp_tx_comp_process_desc(struct dp_soc *soc,
 		if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(desc->nbuf))
 		if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(desc->nbuf))
 			dp_tx_notify_completion(soc, desc, desc->nbuf);
 			dp_tx_notify_completion(soc, desc, desc->nbuf);
 
 
-		dp_tx_comp_process_tx_status(desc, length);
+		dp_tx_comp_process_tx_status(desc, length, peer);
 
 
 		DPTRACE(qdf_dp_trace_ptr
 		DPTRACE(qdf_dp_trace_ptr
 				(desc->nbuf,
 				(desc->nbuf,
@@ -2991,19 +2992,23 @@ static void dp_tx_comp_process_desc(struct dp_soc *soc,
 			);
 			);
 
 
 		/*currently m_copy/tx_capture is not supported for scatter gather packets*/
 		/*currently m_copy/tx_capture is not supported for scatter gather packets*/
-		if (!(desc->msdu_ext_desc) && (dp_get_completion_indication_for_stack(soc,
-					desc->pdev, ts.peer_id, ts.ppdu_id,
+		if (!(desc->msdu_ext_desc) &&
+		    (dp_get_completion_indication_for_stack(soc, desc->pdev,
+					peer, ts.peer_id, ts.ppdu_id,
 					ts.first_msdu, ts.last_msdu,
 					ts.first_msdu, ts.last_msdu,
 					desc->nbuf) == QDF_STATUS_SUCCESS)) {
 					desc->nbuf) == QDF_STATUS_SUCCESS)) {
 			qdf_nbuf_unmap(soc->osdev, desc->nbuf,
 			qdf_nbuf_unmap(soc->osdev, desc->nbuf,
-						QDF_DMA_TO_DEVICE);
+				       QDF_DMA_TO_DEVICE);
 
 
 			dp_send_completion_to_stack(soc, desc->pdev, ts.peer_id,
 			dp_send_completion_to_stack(soc, desc->pdev, ts.peer_id,
-				ts.ppdu_id, desc->nbuf);
+						    ts.ppdu_id, desc->nbuf);
 		} else {
 		} else {
 			dp_tx_comp_free_buf(soc, desc);
 			dp_tx_comp_free_buf(soc, desc);
 		}
 		}
 
 
+		if (peer)
+			dp_peer_unref_del_find_by_id(peer);
+
 		DP_HIST_PACKET_COUNT_INC(desc->pdev->pdev_id);
 		DP_HIST_PACKET_COUNT_INC(desc->pdev->pdev_id);
 
 
 		next = desc->next;
 		next = desc->next;

+ 5 - 3
dp/wifi3.0/dp_tx.h

@@ -197,9 +197,11 @@ static inline void dp_tx_me_exit(struct dp_pdev *pdev)
 
 
 #ifdef FEATURE_PERPKT_INFO
 #ifdef FEATURE_PERPKT_INFO
 QDF_STATUS
 QDF_STATUS
-dp_get_completion_indication_for_stack(struct dp_soc *soc,  struct dp_pdev *pdev,
-		      uint16_t peer_id, uint32_t ppdu_id, uint8_t first_msdu,
-		      uint8_t last_msdu, qdf_nbuf_t netbuf);
+dp_get_completion_indication_for_stack(struct dp_soc *soc,
+				       struct dp_pdev *pdev,
+				       struct dp_peer *peer, uint16_t peer_id,
+				       uint32_t ppdu_id, uint8_t first_msdu,
+				       uint8_t last_msdu, qdf_nbuf_t netbuf);
 
 
 void  dp_send_completion_to_stack(struct dp_soc *soc,  struct dp_pdev *pdev,
 void  dp_send_completion_to_stack(struct dp_soc *soc,  struct dp_pdev *pdev,
 					uint16_t peer_id, uint32_t ppdu_id,
 					uint16_t peer_id, uint32_t ppdu_id,