Bläddra i källkod

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 6 år sedan
förälder
incheckning
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)
 {
 	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,