Browse Source

Merge "qcacmn: Take peer ref count and dec it after using"

Linux Build Service Account 6 years ago
parent
commit
3f0d84bac1

+ 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)
 {
 	uint16_t peer_id;
-	struct dp_peer *peer;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
@@ -1816,8 +1815,7 @@ static void dp_process_ppdu_stats_user_common_tlv(
 		ppdu_desc->vdev_id =
 			HTT_PPDU_STATS_USER_COMMON_TLV_VAP_ID_GET(*tag_buf);
 	} 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;
 	}
 
@@ -1883,7 +1881,6 @@ static void dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev,
 		dp_get_ppdu_info_user_index(pdev,
 					    peer_id, ppdu_info);
 	ppdu_user_desc = &ppdu_desc->user[curr_user_index];
-
 	if (peer_id == DP_SCAN_PEER_ID) {
 		vdev =
 		       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;
 		qdf_mem_copy(ppdu_user_desc->mac_addr,
 			     peer->mac_addr.raw, DP_MAC_ADDR_LEN);
+		dp_peer_unref_del_find_by_id(peer);
 	}
 
 	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;
 	uint8_t curr_user_index = 0;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 
 	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 =
 	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;
 
 	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;
 	uint8_t curr_user_index = 0;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 
 	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 =
 	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;
 
 	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)
 {
 	uint16_t peer_id;
-	struct dp_peer *peer;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
@@ -2050,9 +2041,8 @@ static void dp_process_ppdu_stats_user_cmpltn_common_tlv(
 	tag_buf++;
 	peer_id =
 		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;
 
 	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;
 	uint8_t curr_user_index = 0;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 
 	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 =
 	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;
 
 	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;
 	uint8_t curr_user_index = 0;
 	uint16_t peer_id;
-	struct dp_peer *peer;
 
 	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 =
 	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;
 
 	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)
 {
 	uint16_t peer_id;
-	struct dp_peer *peer;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
@@ -2207,10 +2190,7 @@ static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv(
 	peer_id =
 	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;
 
 	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)
 {
 	uint32_t peer_id;
-	struct dp_peer *peer;
 	struct cdp_tx_completion_ppdu *ppdu_desc;
 	struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
 	uint8_t curr_user_index = 0;
@@ -2262,9 +2241,7 @@ static void dp_process_ppdu_stats_user_common_array_tlv(
 	peer_id =
 		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,
 			"Invalid peer");
 		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)],
 					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
 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 dp_peer *peer = NULL;
@@ -2502,6 +2481,8 @@ void dp_ppdu_desc_deliver(struct dp_pdev *pdev,
 			dp_tx_stats_update(pdev->soc, peer,
 					&ppdu_desc->user[i],
 					ppdu_desc->ack_rssi);
+
+			dp_peer_unref_del_find_by_id(peer);
 		}
 
 		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) {
 				status = dp_addba_requestprocess_wifi3(peer,
 						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_LEVEL_INFO,
 					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,
 	bool force);
 #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_ */

+ 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) {
 		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
 	 * is available
 	 */
+
+	dp_peer_unref_del_find_by_id(peer);
 }
 
 #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_peer *peer;
+	uint8_t vdev_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);
-	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],
 		     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;
 }
 
+#ifdef PEER_PROTECTED_ACCESS
 /**
  * dp_peer_find_by_id() - Returns peer object given the peer id
  *                        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
  */
+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 *
 dp_peer_find_by_id(struct dp_soc *soc,
 		   uint16_t peer_id)
@@ -60,13 +79,13 @@ dp_peer_find_by_id(struct dp_soc *soc,
 	struct dp_peer *peer;
 
 	peer = __dp_peer_find_by_id (soc, peer_id);
-
 	if (peer && peer->delete_in_progress) {
 		return NULL;
 	}
 
 	return peer;
 }
+#endif /* PEER_LOCK_REF_PROTECT */
 
 void dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_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;
 
 }
+
+/*
+ * 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_ */

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

@@ -1527,6 +1527,7 @@ done:
 			qdf_nbuf_free(nbuf);
 			nbuf = next;
 			DP_STATS_INC(soc, rx.err.invalid_vdev, 1);
+			dp_peer_unref_del_find_by_id(peer);
 			continue;
 		}
 
@@ -1590,6 +1591,7 @@ done:
 			qdf_nbuf_free(nbuf);
 			/* Statistics */
 			nbuf = next;
+			dp_peer_unref_del_find_by_id(peer);
 			continue;
 		}
 
@@ -1603,6 +1605,7 @@ done:
 			qdf_nbuf_free(nbuf);
 			/* Statistics */
 			nbuf = next;
+			dp_peer_unref_del_find_by_id(peer);
 			continue;
 		}
 
@@ -1612,6 +1615,7 @@ done:
 			DP_STATS_INC(peer, rx.nawds_mcast_drop, 1);
 			qdf_nbuf_free(nbuf);
 			nbuf = next;
+			dp_peer_unref_del_find_by_id(peer);
 			continue;
 		}
 
@@ -1643,6 +1647,7 @@ done:
 
 				qdf_nbuf_free(nbuf);
 				nbuf = next;
+				dp_peer_unref_del_find_by_id(peer);
 				continue;
 			}
 			dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer);
@@ -1673,6 +1678,7 @@ done:
 							rx_tlv_hdr,
 							nbuf)) {
 					nbuf = next;
+					dp_peer_unref_del_find_by_id(peer);
 					continue; /* Get next desc */
 				}
 		}
@@ -1686,6 +1692,7 @@ done:
 				qdf_nbuf_len(nbuf));
 
 		nbuf = next;
+		dp_peer_unref_del_find_by_id(peer);
 	}
 
 	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);
 void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc,
 		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) \
 	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;
 
 		dp_rx_defrag_waitlist_add(peer, tid);
+		dp_peer_unref_del_find_by_id(peer);
 
 		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_peer_unref_del_find_by_id(peer);
+
 	return QDF_STATUS_SUCCESS;
 
 end:
+	dp_peer_unref_del_find_by_id(peer);
+
 	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[4], peer->mac_addr.raw[5]);
 
+		dp_peer_unref_del_find_by_id(peer);
 	}
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 		"Packet received with PN error");
@@ -547,6 +548,7 @@ free_nbuf:
  * @nbuf: buffer pointer
  * @rx_tlv_hdr: start of rx tlv header
  * @pool_id: mac id
+ * @peer: peer handle
  *
  * This function handles NULL queue descriptor violations arising out
  * a missing REO queue for a given peer or a given TID. This typically
@@ -558,16 +560,13 @@ free_nbuf:
  *
  */
 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;
 	uint16_t msdu_len;
 	struct dp_vdev *vdev;
-	uint16_t peer_id = 0xFFFF;
-	struct dp_peer *peer = NULL;
 	uint8_t tid;
 	struct ether_header *eh;
 
@@ -602,9 +601,6 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc,
 		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) {
 		bool mpdu_done = false;
 		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 */
 	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,
 					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
-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;
 	uint16_t msdu_len;
 	struct dp_vdev *vdev;
-	uint16_t peer_id = 0xFFFF;
-	struct dp_peer *peer = NULL;
 	struct ether_header *eh;
 	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);
 	}
 
-	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);
 	msdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr);
 	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
- * @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
  */
-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_pdev *pdev = NULL;
 	struct ol_if_ops *tops = NULL;
 	struct ieee80211_frame *wh;
 	uint8_t *rx_pkt_hdr;
-	struct dp_peer *peer;
-	uint16_t peer_id, rx_seq, fragno;
+	uint16_t rx_seq, fragno;
 	unsigned int tid;
 	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));
 	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) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-				"peer not found");
+			  "peer not found");
 		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;
 	struct hal_wbm_err_desc_info wbm_err_info = { 0 };
 	uint8_t pool_id;
-	uint16_t peer_id = 0xFFFF;
 	uint8_t tid = 0;
 
 	/* Debug -- Remove later */
@@ -1236,7 +1221,14 @@ done:
 
 	nbuf = nbuf_head;
 	while (nbuf) {
+		struct dp_peer *peer;
+		uint16_t peer_id;
+
 		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
 		 * handle error cases appropriately
@@ -1265,11 +1257,13 @@ done:
 					QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_DP,
 						"Got pkt with REO ERROR: %d",
 						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;
+					if (peer)
+						dp_peer_unref_del_find_by_id(
+									peer);
 					continue;
 				/* TODO */
 				/* Add per error code accounting */
@@ -1288,6 +1282,9 @@ done:
 					dp_2k_jump_handle(soc, nbuf, rx_tlv_hdr,
 							  peer_id, tid);
 					nbuf = next;
+					if (peer)
+						dp_peer_unref_del_find_by_id(
+									peer);
 					continue;
 				default:
 					QDF_TRACE(QDF_MODULE_ID_DP,
@@ -1300,30 +1297,30 @@ done:
 					HAL_RX_WBM_ERR_SRC_RXDMA) {
 			if (wbm_err_info.rxdma_psh_rsn
 					== HAL_RX_WBM_RXDMA_PSH_RSN_ERROR) {
-				struct dp_peer *peer = NULL;
-				uint16_t peer_id = 0xFFFF;
-
 				DP_STATS_INC(soc,
 					rx.err.rxdma_error
 					[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) {
 				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;
+					if (peer)
+						dp_peer_unref_del_find_by_id(
+									peer);
 					continue;
 
 				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;
-					if (peer)
+					if (peer) {
 						DP_STATS_INC(peer, rx.err.mic_err, 1);
+						dp_peer_unref_del_find_by_id(
+									peer);
+					}
 					continue;
 
 				case HAL_RXDMA_ERR_DECRYPT:
@@ -1347,6 +1344,9 @@ done:
 			qdf_assert(0);
 		}
 
+		if (peer)
+			dp_peer_unref_del_find_by_id(peer);
+
 		hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr,
 				     QDF_TRACE_LEVEL_DEBUG);
 		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));
 		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);
+				dp_peer_unref_del_find_by_id(peer);
+			}
 		} else if (pdev->mcopy_mode) {
 			dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC, soc,
 					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
 /**
  * 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
  * @ppdu_id: ppdu_id
  * @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
 */
 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 dp_peer *peer = NULL;
 	struct ether_header *eh;
 
 	if (qdf_unlikely(!pdev->tx_sniffer_enable && !pdev->mcopy_mode))
 		return QDF_STATUS_E_NOSUPPORT;
 
-	peer = (peer_id == HTT_INVALID_PEER) ? NULL :
-			dp_peer_find_by_id(soc, peer_id);
-
 	if (!peer) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				FL("Peer Invalid"));
@@ -2402,9 +2401,11 @@ void  dp_send_completion_to_stack(struct dp_soc *soc,  struct dp_pdev *pdev,
 }
 #else
 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;
 }
@@ -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
  * @tx_desc: software descriptor head pointer
  * @length: packet length
+ * @peer: peer handle
  *
  * 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 dp_soc *soc = NULL;
 	struct dp_vdev *vdev = tx_desc->vdev;
-	struct dp_peer *peer = NULL;
 	struct ether_header *eh =
 		(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);
 
 	/* Update peer level stats */
-	peer = dp_peer_find_by_id(soc, ts.peer_id);
 	if (!peer) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
 				"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))
 			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
 				(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*/
-		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,
 					desc->nbuf) == QDF_STATUS_SUCCESS)) {
 			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,
-				ts.ppdu_id, desc->nbuf);
+						    ts.ppdu_id, desc->nbuf);
 		} else {
 			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);
 
 		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
 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,
 					uint16_t peer_id, uint32_t ppdu_id,