From ce2009b364a776e2d1edff89463093a3459388aa Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Thu, 6 Dec 2018 16:38:34 -0800 Subject: [PATCH] qcacmn: Clean-up all peers in-case of SSR Current driver doesn't clean-up all the peers because the TARGET state is not marked as reset and due to which nobody is there to mimic fake peer unmap events to reduce the reference count. Also, there is no peer delete API being called as well in case of SSR. Identify the TARGET state in-case of SSR by calling HDD callback and mimic the unmap events and call peer delete API as well. CRs-Fixed: 2350285 Change-Id: I878b7a15701c01ac9ef80010086f7e868a631a74 --- dp/wifi3.0/dp_main.c | 26 ++++++++++++++++++++------ hif/src/hif_main.c | 9 +++++++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 2eaec2811cfa..13e5860d0313 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4273,9 +4273,26 @@ static void dp_vdev_flush_peers(struct dp_vdev *vdev) } qdf_spin_unlock_bh(&soc->peer_ref_mutex); - for (i = 0; i < j ; i++) + for (i = 0; i < j ; i++) { + peer = dp_peer_find_by_id(soc, peer_ids[i]); + if (peer) { + dp_info("peer: %pM is getting flush", + peer->mac_addr.raw); + dp_peer_delete_wifi3(peer, 0); + /* + * we need to call dp_peer_unref_del_find_by_id() + * to remove additional ref count incremented + * by dp_peer_find_by_id() call. + * + * Hold the ref count while executing + * dp_peer_delete_wifi3() call. + * + */ + dp_peer_unref_del_find_by_id(peer); + } dp_rx_peer_unmap_handler(soc, peer_ids[i], vdev->vdev_id, NULL, 0); + } qdf_mem_free(peer_ids); @@ -4313,7 +4330,8 @@ static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, * this will free all references held due to missing * unmap commands from Target */ - if (hif_get_target_status(soc->hif_handle) == TARGET_STATUS_RESET) + if ((hif_get_target_status(soc->hif_handle) == TARGET_STATUS_RESET) || + !hif_is_target_ready(HIF_GET_SOFTC(soc->hif_handle))) dp_vdev_flush_peers(vdev); /* @@ -5093,9 +5111,6 @@ void dp_peer_unref_delete(void *peer_handle) uint16_t vdev_id; bool delete_vdev; - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "%s: peer %pK ref_cnt(before decrement): %d\n", __func__, - peer, qdf_atomic_read(&peer->ref_cnt)); /* * Hold the lock all the way from checking if the peer ref count * is zero until the peer references are removed from the hash @@ -5876,7 +5891,6 @@ dp_aggregate_pdev_ctrl_frames_stats(struct dp_pdev *pdev) FL("DP Peer deletion in progress")); continue; } - qdf_atomic_inc(&peer->ref_cnt); waitcnt = 0; dp_peer_rxtid_stats(peer, dp_rx_bar_stats_cb, pdev); diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index cf6f53198130..6ca80a2a2827 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -1131,9 +1131,14 @@ bool hif_is_target_ready(struct hif_softc *scn) if (cbk && cbk->is_target_ready) return cbk->is_target_ready(cbk->context); - - return false; + /* + * if callback is not registered then there is no way to determine + * if target is ready. In-such case return true to indicate that + * target is ready. + */ + return true; } +qdf_export_symbol(hif_is_target_ready); /** * hif_batch_send() - API to access hif specific function