diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 95c2e3e94568..1dcb930243ad 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/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"), diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 033e2e5fc143..9b1eb080c37b 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/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_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index bd4b707f3b12..e5eda38e4576 100644 --- a/dp/wifi3.0/dp_main.c +++ b/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); } } } diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 6f61366ad424..0b540e2fed39 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/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; +} diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 16ea4c62c185..47c0f7c35915 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/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_ */ diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 032c25815a49..f01b0d11ed54 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/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) diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 099a81fc9610..63e9b14fc280 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/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 { \ diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index 004570ef8d34..dc6d3c74433e 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/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; } diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 525fc04728b4..d4e1f9084f6c 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/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); diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c index 53d308a3571d..8519df8ec6d0 100644 --- a/dp/wifi3.0/dp_rx_mon_status.c +++ b/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, diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 78a88f1d4a4c..838516d71596 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/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; diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index dcb015cef28b..a4fb6735bd2b 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/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,