diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index 78f08eef1e4c..388c1cfd1e76 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -1370,7 +1370,8 @@ static inline int ol_tx_encap_wrapper(struct ol_txrx_pdev_t *pdev, ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1); if (tx_msdu_info->peer) { /* remove the peer reference added above */ - OL_TXRX_PEER_UNREF_DELETE(tx_msdu_info->peer); + ol_txrx_peer_release_ref(tx_msdu_info->peer, + PEER_DEBUG_ID_OL_INTERNAL); } return -EINVAL; } @@ -1571,7 +1572,8 @@ int ol_txrx_mgmt_send_frame( out: if (tx_msdu_info->peer) { /* remove the peer reference added above */ - OL_TXRX_PEER_UNREF_DELETE(tx_msdu_info->peer); + ol_txrx_peer_release_ref(tx_msdu_info->peer, + PEER_DEBUG_ID_OL_INTERNAL); } return status; @@ -1760,8 +1762,9 @@ ol_tx_hl_base( if (tx_msdu_info.peer) { /* remove the peer reference * added above */ - OL_TXRX_PEER_UNREF_DELETE( - tx_msdu_info.peer); + ol_txrx_peer_release_ref( + tx_msdu_info.peer, + PEER_DEBUG_ID_OL_INTERNAL); } goto MSDU_LOOP_BOTTOM; } @@ -1778,8 +1781,9 @@ ol_tx_hl_base( ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1); - OL_TXRX_PEER_UNREF_DELETE( - tx_msdu_info.peer); + ol_txrx_peer_release_ref( + tx_msdu_info.peer, + PEER_DEBUG_ID_OL_INTERNAL); msdu = next; continue; } else if (tx_msdu_info.peer->state != @@ -1794,8 +1798,9 @@ ol_tx_hl_base( ol_tx_desc_frame_free_nonstd( pdev, tx_desc, 1); - OL_TXRX_PEER_UNREF_DELETE( - tx_msdu_info.peer); + ol_txrx_peer_release_ref( + tx_msdu_info.peer, + PEER_DEBUG_ID_OL_INTERNAL); msdu = next; continue; } @@ -1843,7 +1848,9 @@ ol_tx_hl_base( OL_TX_PEER_STATS_UPDATE(tx_msdu_info.peer, msdu); /* remove the peer reference added above */ - OL_TXRX_PEER_UNREF_DELETE(tx_msdu_info.peer); + ol_txrx_peer_release_ref + (tx_msdu_info.peer, + PEER_DEBUG_ID_OL_INTERNAL); } MSDU_LOOP_BOTTOM: msdu = next; diff --git a/core/dp/txrx/ol_tx_classify.c b/core/dp/txrx/ol_tx_classify.c index 6094ac9a82b2..cd880f458172 100644 --- a/core/dp/txrx/ol_tx_classify.c +++ b/core/dp/txrx/ol_tx_classify.c @@ -357,7 +357,8 @@ struct ol_txrx_peer_t *ol_tx_tdls_peer_find(struct ol_txrx_pdev_t *pdev, peer = NULL; } else { if (peer) - OL_TXRX_PEER_INC_REF_CNT(peer); + ol_txrx_peer_get_ref(peer, + PEER_DEBUG_ID_OL_INTERNAL); } } if (!peer) @@ -464,9 +465,11 @@ ol_tx_classify( * classify_extension function can check whether to * encrypt multicast / broadcast frames. */ - peer = ol_txrx_peer_find_hash_find_inc_ref(pdev, - vdev->mac_addr.raw, - 0, 1); + peer = ol_txrx_peer_find_hash_find_get_ref + (pdev, + vdev->mac_addr.raw, + 0, 1, + PEER_DEBUG_ID_OL_INTERNAL); if (!peer) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, @@ -523,9 +526,10 @@ ol_tx_classify( */ peer = ol_tx_tdls_peer_find(pdev, vdev, &peer_id); } else { - peer = ol_txrx_peer_find_hash_find_inc_ref(pdev, - dest_addr, - 0, 1); + peer = ol_txrx_peer_find_hash_find_get_ref(pdev, + dest_addr, + 0, 1, + PEER_DEBUG_ID_OL_INTERNAL); } tx_msdu_info->htt.info.is_unicast = true; if (!peer) { @@ -583,7 +587,9 @@ ol_tx_classify( "%s: remove the peer for invalid peer_id %pK\n", __func__, peer); /* remove the peer reference added above */ - OL_TXRX_PEER_UNREF_DELETE(peer); + ol_txrx_peer_release_ref + (peer, + PEER_DEBUG_ID_OL_INTERNAL); tx_msdu_info->peer = NULL; } return NULL; @@ -606,7 +612,8 @@ ol_tx_classify( "%s: remove the peer reference %pK\n", __func__, peer); /* remove the peer reference added above */ - OL_TXRX_PEER_UNREF_DELETE(tx_msdu_info->peer); + ol_txrx_peer_release_ref(tx_msdu_info->peer, + PEER_DEBUG_ID_OL_INTERNAL); /* Making peer NULL in case if multicast non STA mode */ tx_msdu_info->peer = NULL; } @@ -680,24 +687,26 @@ ol_tx_classify_mgmt( * frame to vdev queue. */ if (peer) { - int rcnt; qdf_mem_copy( &local_mac_addr_aligned.raw[0], dest_addr, OL_TXRX_MAC_ADDR_LEN); mac_addr = &local_mac_addr_aligned; - if (ol_txrx_peer_find_mac_addr_cmp( - mac_addr, - &peer->mac_addr) != 0) { - rcnt = OL_TXRX_PEER_UNREF_DELETE(peer); + if (ol_txrx_peer_find_mac_addr_cmp + (mac_addr, + &peer->mac_addr) != 0) { + ol_txrx_peer_release_ref + (peer, + PEER_DEBUG_ID_OL_INTERNAL); peer = NULL; } } } else { /* find the peer and increment its reference count */ - peer = ol_txrx_peer_find_hash_find_inc_ref(pdev, - dest_addr, - 0, 1); + peer = ol_txrx_peer_find_hash_find_get_ref(pdev, + dest_addr, + 0, 1, + PEER_DEBUG_ID_OL_INTERNAL); } tx_msdu_info->peer = peer; if (!peer) { diff --git a/core/dp/txrx/ol_tx_queue.c b/core/dp/txrx/ol_tx_queue.c index 0fcc453663c0..a9a02594172a 100644 --- a/core/dp/txrx/ol_tx_queue.c +++ b/core/dp/txrx/ol_tx_queue.c @@ -111,7 +111,9 @@ ol_tx_queue_vdev_flush(struct ol_txrx_pdev_t *pdev, struct ol_txrx_vdev_t *vdev) for (i = 0; i < OL_TX_NUM_TIDS; i++) { txq = &peer->txqs[i]; if (txq->frms) { - OL_TXRX_PEER_INC_REF_CNT(peer); + ol_txrx_peer_get_ref + (peer, + PEER_DEBUG_ID_OL_INTERNAL); peers[peer_count++] = peer; break; } @@ -129,7 +131,8 @@ ol_tx_queue_vdev_flush(struct ol_txrx_pdev_t *pdev, struct ol_txrx_vdev_t *vdev) } ol_txrx_info( "%s: Delete Peer %pK\n", __func__, peer); - OL_TXRX_PEER_UNREF_DELETE(peers[i]); + ol_txrx_peer_release_ref(peers[i], + PEER_DEBUG_ID_OL_INTERNAL); } } while (peer_count >= PEER_ARRAY_COUNT); } diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index c06dd0f2c35b..bc595dadaf0b 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -319,7 +319,7 @@ ol_txrx_find_peer_by_addr_and_vdev(struct cdp_pdev *ppdev, if (!peer) return NULL; *peer_id = peer->local_id; - OL_TXRX_PEER_UNREF_DELETE(peer); + ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); return peer; } @@ -385,16 +385,17 @@ void *ol_txrx_find_peer_by_addr(struct cdp_pdev *ppdev, struct ol_txrx_peer_t *peer; struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev; - peer = ol_txrx_peer_find_hash_find_inc_ref(pdev, peer_addr, 0, 1); + peer = ol_txrx_peer_find_hash_find_get_ref(pdev, peer_addr, 0, 1, + PEER_DEBUG_ID_OL_INTERNAL); if (!peer) return NULL; *peer_id = peer->local_id; - OL_TXRX_PEER_UNREF_DELETE(peer); + ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); return peer; } /** - * ol_txrx_find_peer_by_addr_inc_ref() - find peer via peer mac addr and peer_id + * ol_txrx_peer_get_ref_by_addr() - get peer ref via peer mac addr and peer_id * @pdev: pointer of type ol_txrx_pdev_handle * @peer_addr: peer mac addr * @peer_id: pointer to fill in the value of peer->local_id for caller @@ -402,28 +403,30 @@ void *ol_txrx_find_peer_by_addr(struct cdp_pdev *ppdev, * This function finds the peer with given mac address and returns its peer_id. * Note that this function increments the peer->ref_cnt. * This makes sure that peer will be valid. This also means the caller needs to - * call the corresponding API - OL_TXRX_PEER_UNREF_DELETE to delete the peer + * call the corresponding API - ol_txrx_peer_release_ref to delete the peer * reference. * Sample usage: * { * //the API call below increments the peer->ref_cnt - * peer = ol_txrx_find_peer_by_addr_inc_ref(pdev, peer_addr, peer_id); + * peer = ol_txrx_peer_get_ref_by_addr(pdev, peer_addr, peer_id, dbg_id); * * // Once peer usage is done * * //the API call below decrements the peer->ref_cnt - * OL_TXRX_PEER_UNREF_DELETE(peer); + * ol_txrx_peer_release_ref(peer, dbg_id); * } * * Return: peer handle if the peer is found, NULL if peer is not found. */ -ol_txrx_peer_handle ol_txrx_find_peer_by_addr_inc_ref(ol_txrx_pdev_handle pdev, - uint8_t *peer_addr, - uint8_t *peer_id) +ol_txrx_peer_handle ol_txrx_peer_get_ref_by_addr(ol_txrx_pdev_handle pdev, + u8 *peer_addr, + u8 *peer_id, + enum peer_debug_id_type dbg_id) { struct ol_txrx_peer_t *peer; - peer = ol_txrx_peer_find_hash_find_inc_ref(pdev, peer_addr, 0, 1); + peer = ol_txrx_peer_find_hash_find_get_ref(pdev, peer_addr, 0, 1, + dbg_id); if (!peer) return NULL; *peer_id = peer->local_id; @@ -2644,10 +2647,13 @@ ol_txrx_peer_attach(struct cdp_vdev *pvdev, uint8_t *peer_mac_addr) qdf_atomic_init(&peer->delete_in_progress); qdf_atomic_init(&peer->flush_in_progress); - qdf_atomic_init(&peer->ref_cnt); + + for (i = 0; i < PEER_DEBUG_ID_MAX; i++) + qdf_atomic_init(&peer->access_list[i]); + /* keep one reference for attach */ - OL_TXRX_PEER_INC_REF_CNT(peer); + ol_txrx_peer_get_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); /* Set a flag to indicate peer create is pending in firmware */ qdf_atomic_init(&peer->fw_create_pending); @@ -3073,7 +3079,8 @@ QDF_STATUS ol_txrx_peer_state_update(struct cdp_pdev *ppdev, return QDF_STATUS_E_INVAL; } - peer = ol_txrx_peer_find_hash_find_inc_ref(pdev, peer_mac, 0, 1); + peer = ol_txrx_peer_find_hash_find_get_ref(pdev, peer_mac, 0, 1, + PEER_DEBUG_ID_OL_INTERNAL); if (NULL == peer) { ol_txrx_err( "%s: peer is null for peer_mac 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", @@ -3091,7 +3098,9 @@ QDF_STATUS ol_txrx_peer_state_update(struct cdp_pdev *ppdev, "%s: no state change, returns directly\n", __func__); #endif - peer_ref_cnt = OL_TXRX_PEER_UNREF_DELETE(peer); + peer_ref_cnt = ol_txrx_peer_release_ref + (peer, + PEER_DEBUG_ID_OL_INTERNAL); return QDF_STATUS_SUCCESS; } @@ -3121,9 +3130,10 @@ QDF_STATUS ol_txrx_peer_state_update(struct cdp_pdev *ppdev, ol_txrx_peer_tid_unpause(peer, tid); } } - peer_ref_cnt = OL_TXRX_PEER_UNREF_DELETE(peer); + peer_ref_cnt = ol_txrx_peer_release_ref(peer, + PEER_DEBUG_ID_OL_INTERNAL); /* - * after OL_TXRX_PEER_UNREF_DELETE, peer object cannot be accessed + * after ol_txrx_peer_release_ref, peer object cannot be accessed * if the return code was 0 */ if (peer_ref_cnt > 0) @@ -3148,9 +3158,9 @@ ol_txrx_peer_update(ol_txrx_vdev_handle vdev, enum ol_txrx_peer_update_select_t select) { struct ol_txrx_peer_t *peer; - int peer_ref_cnt; - peer = ol_txrx_peer_find_hash_find_inc_ref(vdev->pdev, peer_mac, 0, 1); + peer = ol_txrx_peer_find_hash_find_get_ref(vdev->pdev, peer_mac, 0, 1, + PEER_DEBUG_ID_OL_INTERNAL); if (!peer) { ol_txrx_dbg("%s: peer is null", __func__); @@ -3231,7 +3241,7 @@ ol_txrx_peer_update(ol_txrx_vdev_handle vdev, break; } } /* switch */ - peer_ref_cnt = OL_TXRX_PEER_UNREF_DELETE(peer); + ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); } uint8_t @@ -3257,14 +3267,71 @@ ol_txrx_peer_qoscapable_get(struct ol_txrx_pdev_t *txrx_pdev, uint16_t peer_id) return 0; } -int ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer, - const char *fname, - int line) +/** + * ol_txrx_dump_peer_access_list() - dump peer access list + * @peer: peer handle + * + * This function will dump if any peer debug ids are still accessing peer + * + * Return: None + */ +static void ol_txrx_dump_peer_access_list(ol_txrx_peer_handle peer) +{ + u32 i; + u32 pending_ref; + + for (i = 0; i < PEER_DEBUG_ID_MAX; i++) { + pending_ref = qdf_atomic_read(&peer->access_list[i]); + if (pending_ref) + ol_txrx_info_high("id %d pending refs %d", + i, pending_ref); + } +} + +/** + * ol_txrx_peer_free_tids() - free tids for the peer + * @peer: peer handle + * + * Return: None + */ +static inline void ol_txrx_peer_free_tids(ol_txrx_peer_handle peer) +{ + int i = 0; + /* + * 'array' is allocated in addba handler and is supposed to be + * freed in delba handler. There is the case (for example, in + * SSR) where delba handler is not called. Because array points + * to address of 'base' by default and is reallocated in addba + * handler later, only free the memory when the array does not + * point to base. + */ + for (i = 0; i < OL_TXRX_NUM_EXT_TIDS; i++) { + if (peer->tids_rx_reorder[i].array != + &peer->tids_rx_reorder[i].base) { + ol_txrx_dbg( + "%s, delete reorder arr, tid:%d\n", + __func__, i); + qdf_mem_free(peer->tids_rx_reorder[i].array); + ol_rx_reorder_init(&peer->tids_rx_reorder[i], + (uint8_t)i); + } + } +} + +/** + * ol_txrx_peer_release_ref() - release peer reference + * @peer: peer handle + * + * Release peer reference and delete peer if refcount is 0 + * + * Return: None + */ +int ol_txrx_peer_release_ref(ol_txrx_peer_handle peer, + enum peer_debug_id_type debug_id) { int rc; struct ol_txrx_vdev_t *vdev; struct ol_txrx_pdev_t *pdev; - int i; /* preconditions */ TXRX_ASSERT2(peer); @@ -3283,6 +3350,11 @@ int ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer, return -EINVAL; } + if (debug_id >= PEER_DEBUG_ID_MAX || debug_id < 0) { + ol_txrx_err("incorrect debug_id %d ", debug_id); + return -EINVAL; + } + wlan_roam_debug_log(vdev->vdev_id, DEBUG_PEER_UNREF_DELETE, DEBUG_INVALID_PEER_ID, &peer->mac_addr.raw, peer, 0, @@ -3323,14 +3395,19 @@ int ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer, */ rc--; + if (!qdf_atomic_read(&peer->access_list[debug_id])) { + qdf_spin_unlock_bh(&pdev->peer_ref_mutex); + ol_txrx_err("peer %p ref was not taken by %d", + peer, debug_id); + ol_txrx_dump_peer_access_list(peer); + QDF_BUG(0); + return -EACCES; + } + + qdf_atomic_dec(&peer->access_list[debug_id]); + if (qdf_atomic_dec_and_test(&peer->ref_cnt)) { - u_int16_t peer_id; - - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, - "[%s][%d]: Deleting peer %pK (%pM) ref_cnt %d\n", - fname, line, peer, peer->mac_addr.raw, - qdf_atomic_read(&peer->ref_cnt)); - + u16 peer_id; wlan_roam_debug_log(vdev->vdev_id, DEBUG_DELETING_PEER_OBJ, DEBUG_INVALID_PEER_ID, @@ -3410,46 +3487,31 @@ int ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer, qdf_spin_unlock_bh(&pdev->peer_ref_mutex); } - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "[%s][%d]: Deleting peer %pK (%pM) peer->ref_cnt = %d %s", - fname, line, peer, peer->mac_addr.raw, - qdf_atomic_read(&peer->ref_cnt), - qdf_atomic_read(&peer->fw_create_pending) == 1 ? - "(No Maps received)" : ""); + ol_txrx_info_high("[%d][%d]: Deleting peer %p ref_cnt -> %d %s", + debug_id, + qdf_atomic_read(&peer->access_list[debug_id]), + peer, rc, + qdf_atomic_read(&peer->fw_create_pending) + == 1 ? + "(No Maps received)" : ""); ol_txrx_peer_tx_queue_free(pdev, peer); /* Remove mappings from peer_id to peer object */ ol_txrx_peer_clear_map_peer(pdev, peer); - /* - * 'array' is allocated in addba handler and is supposed to be - * freed in delba handler. There is the case (for example, in - * SSR) where delba handler is not called. Because array points - * to address of 'base' by default and is reallocated in addba - * handler later, only free the memory when the array does not - * point to base. - */ - for (i = 0; i < OL_TXRX_NUM_EXT_TIDS; i++) { - if (peer->tids_rx_reorder[i].array != - &peer->tids_rx_reorder[i].base) { - ol_txrx_dbg( - "%s, delete reorder arr, tid:%d\n", - __func__, i); - qdf_mem_free(peer->tids_rx_reorder[i].array); - ol_rx_reorder_init(&peer->tids_rx_reorder[i], - (uint8_t) i); - } - } + ol_txrx_peer_free_tids(peer); + + ol_txrx_dump_peer_access_list(peer); qdf_mem_free(peer); } else { qdf_spin_unlock_bh(&pdev->peer_ref_mutex); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "[%s][%d]: ref delete peer %pK peer->ref_cnt = %d", - fname, line, peer, rc); + ol_txrx_info_high("[%d][%d]: ref delete peer %p ref_cnt -> %d", + debug_id, + qdf_atomic_read(&peer->access_list[debug_id]), + peer, rc); } - return rc; } @@ -3612,12 +3674,10 @@ static void ol_txrx_peer_detach(void *ppeer, uint32_t bitmap) if (vdev->opmode == wlan_op_mode_sta) { qdf_timer_start(&peer->peer_unmap_timer, OL_TXRX_PEER_UNMAP_TIMEOUT); - ol_txrx_info_high("%s: started peer_unmap_timer for peer %pK", - __func__, peer); + ol_txrx_info_high + ("started peer_unmap_timer for peer %pK", + peer); } - } else { - ol_txrx_err("%s unmap timer not started as PEER_DELETE not sent to FW", - __func__); } /* @@ -3626,7 +3686,7 @@ static void ol_txrx_peer_detach(void *ppeer, uint32_t bitmap) * PEER_UNMAP message arrives to remove the other * reference, added by the PEER_MAP message. */ - OL_TXRX_PEER_UNREF_DELETE(peer); + ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); } /** @@ -3653,21 +3713,6 @@ static void ol_txrx_peer_detach_force_delete(void *ppeer) ol_txrx_peer_detach(peer, CDP_PEER_DELETE_NO_SPECIAL); } -ol_txrx_peer_handle -ol_txrx_peer_find_by_addr(struct ol_txrx_pdev_t *pdev, uint8_t *peer_mac_addr) -{ - struct ol_txrx_peer_t *peer; - - peer = ol_txrx_peer_find_hash_find_inc_ref(pdev, peer_mac_addr, 0, 0); - if (peer) { - ol_txrx_info_high( - "%s: Delete extra reference %pK", __func__, peer); - /* release the extra reference */ - OL_TXRX_PEER_UNREF_DELETE(peer); - } - return peer; -} - /** * ol_txrx_dump_tx_desc() - dump tx desc total and free count * @txrx_pdev: Pointer to txrx pdev @@ -4315,14 +4360,15 @@ static void ol_txrx_disp_peer_stats(ol_txrx_pdev_handle pdev) qdf_spin_lock_bh(&pdev->local_peer_ids.lock); peer = pdev->local_peer_ids.map[i]; if (peer) - OL_TXRX_PEER_INC_REF_CNT(peer); + ol_txrx_peer_get_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); qdf_spin_unlock_bh(&pdev->local_peer_ids.lock); if (peer) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "stats: peer 0x%pK local peer id %d", peer, i); ol_txrx_disp_peer_cached_bufq_stats(peer); - OL_TXRX_PEER_UNREF_DELETE(peer); + ol_txrx_peer_release_ref(peer, + PEER_DEBUG_ID_OL_INTERNAL); } } } @@ -5590,6 +5636,39 @@ static void *ol_txrx_wrapper_find_peer_by_addr(struct cdp_pdev *pdev, peer_addr, peer_id); } +/** + * ol_txrx_wrapper_peer_get_ref_by_addr() - get peer reference by address + * @pdev: pdev handle + * @peer_addr: peer address we want to find + * @peer_id: peer id + * @debug_id: peer debug id for tracking + * + * Return: peer instance pointer + */ +static void * +ol_txrx_wrapper_peer_get_ref_by_addr(struct cdp_pdev *pdev, + u8 *peer_addr, uint8_t *peer_id, + enum peer_debug_id_type debug_id) +{ + return ol_txrx_peer_get_ref_by_addr((ol_txrx_pdev_handle)pdev, + peer_addr, peer_id, debug_id); +} + +/** + * ol_txrx_wrapper_peer_release_ref() - release peer reference + * @peer: peer handle + * @debug_id: peer debug id for tracking + * + * Release peer ref acquired by peer get ref api + * + * Return: void + */ +static void ol_txrx_wrapper_peer_release_ref(void *peer, + enum peer_debug_id_type debug_id) +{ + ol_txrx_peer_release_ref(peer, debug_id); +} + /** * ol_txrx_wrapper_set_flow_control_parameters() - set flow control parameters * @cfg_ctx: cfg context @@ -5749,6 +5828,8 @@ static struct cdp_cfg_ops ol_ops_cfg = { static struct cdp_peer_ops ol_ops_peer = { .register_peer = ol_txrx_wrapper_register_peer, .clear_peer = ol_txrx_clear_peer, + .peer_get_ref_by_addr = ol_txrx_wrapper_peer_get_ref_by_addr, + .peer_release_ref = ol_txrx_wrapper_peer_release_ref, .find_peer_by_addr = ol_txrx_wrapper_find_peer_by_addr, .find_peer_by_addr_and_vdev = ol_txrx_find_peer_by_addr_and_vdev, .local_peer_id = ol_txrx_local_peer_id, diff --git a/core/dp/txrx/ol_txrx.h b/core/dp/txrx/ol_txrx.h index 036fb2ac5c0e..eb37ece377b6 100644 --- a/core/dp/txrx/ol_txrx.h +++ b/core/dp/txrx/ol_txrx.h @@ -39,16 +39,16 @@ * only for forwarding path. */ #define OL_TX_NON_FWD_RESERVE 100 -#define OL_TXRX_PEER_UNREF_DELETE(peer) \ - ol_txrx_peer_unref_delete(peer, __func__, __LINE__); -int ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer, - const char *fname, - int line); +ol_txrx_peer_handle ol_txrx_peer_get_ref_by_addr(ol_txrx_pdev_handle pdev, + u8 *peer_addr, + u8 *peer_id, + enum peer_debug_id_type + dbg_id); + +int ol_txrx_peer_release_ref(ol_txrx_peer_handle peer, + enum peer_debug_id_type dbg_id); -ol_txrx_peer_handle ol_txrx_find_peer_by_addr_inc_ref(ol_txrx_pdev_handle pdev, - uint8_t *peer_addr, - uint8_t *peer_id); /** * ol_tx_desc_pool_size_hl() - allocate tx descriptor pool size for HL systems * @ctrl_pdev: the control pdev handle diff --git a/core/dp/txrx/ol_txrx_peer_find.c b/core/dp/txrx/ol_txrx_peer_find.c index fad184b6fee5..4ebd0fcc0e6b 100644 --- a/core/dp/txrx/ol_txrx_peer_find.c +++ b/core/dp/txrx/ol_txrx_peer_find.c @@ -40,7 +40,7 @@ #include /* ol_txrx_pdev_t, etc. */ #include /* TXRX_DEBUG_LEVEL */ #include /* ol_txrx_pdev_t, etc. */ -#include /* ol_txrx_peer_unref_delete */ +#include /* ol_txrx_peer_release_ref */ #include /* ol_txrx_peer_find_attach, etc. */ #include #include "wlan_roam_debug.h" @@ -70,24 +70,28 @@ static int ol_txrx_log2_ceil(unsigned int value) return log2; } -/** - * __ol_txrx_peer_change_ref_cnt() - change peer ref count by the input value - * @peer: pointer to peer structure - * @change: value to add to the peer->ref_cnt, can be negative - * @fname: name of the calling function - * @line: line number of the calling function - * - * Return: the QDF_STATUS return from hdd_execute_config_command - */ -void __ol_txrx_peer_change_ref_cnt(struct ol_txrx_peer_t *peer, - int change, - const char *fname, - int line) +int ol_txrx_peer_get_ref(struct ol_txrx_peer_t *peer, + enum peer_debug_id_type dbg_id) { - qdf_atomic_add(change, &peer->ref_cnt); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "[%s][%d]: peer %pK peer->ref_cnt changed by (%d) to %d", - fname, line, peer, change, qdf_atomic_read(&peer->ref_cnt)); + int refs_dbg_id; + + if (!peer) { + ol_txrx_err("peer is null for ID %d", dbg_id); + return -EINVAL; + } + + if (dbg_id >= PEER_DEBUG_ID_MAX || dbg_id < 0) { + ol_txrx_err("incorrect debug_id %d ", dbg_id); + return -EINVAL; + } + + qdf_atomic_inc(&peer->ref_cnt); + qdf_atomic_inc(&peer->access_list[dbg_id]); + refs_dbg_id = qdf_atomic_read(&peer->access_list[dbg_id]); + ol_txrx_info_high("[%d][%d] peer %pK ref_cnt -> %d", + dbg_id, refs_dbg_id, + peer, qdf_atomic_read(&peer->ref_cnt)); + return refs_dbg_id; } /*=== function definitions for peer MAC addr --> peer object hash table =====*/ @@ -199,9 +203,8 @@ struct ol_txrx_peer_t *ol_txrx_peer_vdev_find_hash(struct ol_txrx_pdev_t *pdev, if (ol_txrx_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0 && (check_valid == 0 || peer->valid) && peer->vdev == vdev) { - /* found it */ - OL_TXRX_PEER_INC_REF_CNT(peer); + ol_txrx_peer_get_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); qdf_spin_unlock_bh(&pdev->peer_ref_mutex); return peer; } @@ -211,11 +214,12 @@ struct ol_txrx_peer_t *ol_txrx_peer_vdev_find_hash(struct ol_txrx_pdev_t *pdev, } struct ol_txrx_peer_t * -ol_txrx_peer_find_hash_find_inc_ref + ol_txrx_peer_find_hash_find_get_ref (struct ol_txrx_pdev_t *pdev, uint8_t *peer_mac_addr, int mac_addr_is_aligned, - uint8_t check_valid) + u8 check_valid, + enum peer_debug_id_type dbg_id) { union ol_txrx_align_mac_addr_t local_mac_addr_aligned, *mac_addr; unsigned int index; @@ -234,7 +238,7 @@ ol_txrx_peer_find_hash_find_inc_ref if (ol_txrx_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0 && (check_valid == 0 || peer->valid)) { /* found it */ - OL_TXRX_PEER_INC_REF_CNT(peer); + ol_txrx_peer_get_ref(peer, dbg_id); qdf_spin_unlock_bh(&pdev->peer_ref_mutex); return peer; } @@ -296,11 +300,9 @@ void ol_txrx_peer_find_hash_erase(struct ol_txrx_pdev_t *pdev) /* * Artificially adjust the peer's ref count to * 1, so it will get deleted by - * OL_TXRX_PEER_UNREF_DELETE. + * ol_txrx_peer_release_ref. */ qdf_atomic_init(&peer->ref_cnt); /* set to 0 */ - OL_TXRX_PEER_INC_REF_CNT(peer); /* incr to 1 */ - OL_TXRX_PEER_UNREF_DELETE(peer); } } } @@ -383,8 +385,9 @@ static inline void ol_txrx_peer_find_add_id(struct ol_txrx_pdev_t *pdev, /* check if there's already a peer object with this MAC address */ peer = - ol_txrx_peer_find_hash_find_inc_ref(pdev, peer_mac_addr, - 1 /* is aligned */, 0); + ol_txrx_peer_find_hash_find_get_ref(pdev, peer_mac_addr, + 1 /* is aligned */, 0, + PEER_DEBUG_ID_OL_INTERNAL); if (!peer || peer_id == HTT_INVALID_PEER) { /* @@ -644,7 +647,7 @@ void ol_rx_peer_unmap_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id) * Remove a reference to the peer. * If there are no more references, delete the peer object. */ - OL_TXRX_PEER_UNREF_DELETE(peer); + ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "%s: peer_id %d peer %pK peer_id_ref_cnt %d", @@ -695,7 +698,7 @@ void ol_txrx_peer_remove_obj_map_entries(ol_txrx_pdev_handle pdev, /* * Transfer peer_id_ref_cnt into del_peer_id_ref_cnt so that - * OL_TXRX_PEER_UNREF_DELETE will decrement del_peer_id_ref_cnt + * ol_txrx_peer_release_ref will decrement del_peer_id_ref_cnt * and any map events will increment peer_id_ref_cnt. Otherwise * accounting will be messed up. * @@ -722,7 +725,7 @@ void ol_txrx_peer_remove_obj_map_entries(ol_txrx_pdev_handle pdev, } while (num_deleted_maps-- > 0) - OL_TXRX_PEER_UNREF_DELETE(peer); + ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL); } struct ol_txrx_peer_t *ol_txrx_assoc_peer_find(struct ol_txrx_vdev_t *vdev) @@ -736,7 +739,8 @@ struct ol_txrx_peer_t *ol_txrx_assoc_peer_find(struct ol_txrx_vdev_t *vdev) */ if (vdev->last_real_peer && vdev->last_real_peer->peer_ids[0] != HTT_INVALID_PEER_ID) { - OL_TXRX_PEER_INC_REF_CNT(vdev->last_real_peer); + ol_txrx_peer_get_ref(vdev->last_real_peer, + PEER_DEBUG_ID_OL_INTERNAL); peer = vdev->last_real_peer; } else { peer = NULL; diff --git a/core/dp/txrx/ol_txrx_peer_find.h b/core/dp/txrx/ol_txrx_peer_find.h index 69ed091deb8b..03a3177d256d 100644 --- a/core/dp/txrx/ol_txrx_peer_find.h +++ b/core/dp/txrx/ol_txrx_peer_find.h @@ -36,14 +36,20 @@ #include /* ol_txrx_pdev_t, etc. */ #include /* TXRX_ASSERT */ +/** + * ol_txrx_peer_get_ref() - get peer reference + * @peer: peer for removing obj map entries + * @dbg_id: debug id to keep track of peer references + * + * The function increments the peer ref count. The ref count can be reduced by + * caling ol_txrx_peer_release_ref function. + * + * Return: peer debug id ref count or error + */ +int +ol_txrx_peer_get_ref(struct ol_txrx_peer_t *peer, + enum peer_debug_id_type dbg_id); -#define OL_TXRX_PEER_INC_REF_CNT(peer) \ - __ol_txrx_peer_change_ref_cnt(peer, 1, __func__, __LINE__); - -void __ol_txrx_peer_change_ref_cnt(struct ol_txrx_peer_t *peer, - int change, - const char *fname, - int line); int ol_txrx_peer_find_attach(struct ol_txrx_pdev_t *pdev); void ol_txrx_peer_find_detach(struct ol_txrx_pdev_t *pdev); @@ -97,11 +103,12 @@ ol_txrx_peer_find_hash_add(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer); struct ol_txrx_peer_t * -ol_txrx_peer_find_hash_find_inc_ref + ol_txrx_peer_find_hash_find_get_ref (struct ol_txrx_pdev_t *pdev, uint8_t *peer_mac_addr, int mac_addr_is_aligned, - uint8_t check_valid); + u8 check_valid, + enum peer_debug_id_type dbg_id); struct ol_txrx_peer_t *ol_txrx_peer_vdev_find_hash(struct ol_txrx_pdev_t *pdev, diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index 21ee9bd08545..e5c9064d3cbc 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -1207,6 +1207,7 @@ struct ol_txrx_peer_t { struct ol_txrx_vdev_t *vdev; qdf_atomic_t ref_cnt; + qdf_atomic_t access_list[PEER_DEBUG_ID_MAX]; qdf_atomic_t delete_in_progress; qdf_atomic_t flush_in_progress;