From 4863352e5379872f610f869d0a2afe60161d4f22 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Fri, 15 Nov 2019 15:07:53 +0530 Subject: [PATCH] qcacmn: Unmap the htc connect buffer after connect failure The htc connect message buffer is not unmapped, if the firmware does not send wmi ready event to the host. Scenario: - Host sends htc init command. - The command is queued into the src ring. - The firmware has crashed before the Copy Engine could copy the message to the destination ring - Due to the above point, no copy completion interrupt is received. - The host times out during its wait for the wmi ready event. - Hence the htc init command buffer stays unmapped and unfreed. As a part of the wma ready event missing cleanup, the htc connect buffer is not unmapped. Fix this to avoid missing to unmap the buffer. To avoid a side effect of sending a completion for HTC connect command, all the commands are freed in the htc completion handler in case of SSR. CRs-Fixed: 2512344 Change-Id: I05026b3cbb764197e6df85c41634002d271a50e5 --- hif/src/ce/ce_main.c | 20 +++++--------------- htc/htc.c | 24 +++++++++++++++--------- htc/htc_send.c | 9 +++++++++ 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index f5661a28b8..69ca818bbf 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -2129,8 +2129,6 @@ hif_pci_ce_send_done(struct CE_handle *copyeng, void *ce_context, { struct HIF_CE_pipe_info *pipe_info = (struct HIF_CE_pipe_info *)ce_context; - struct HIF_CE_state *hif_state = pipe_info->HIF_CE_state; - struct hif_softc *scn = HIF_GET_SOFTC(hif_state); unsigned int sw_idx = sw_index, hw_idx = hw_index; struct hif_msg_callbacks *msg_callbacks = &pipe_info->pipe_callbacks; @@ -2140,19 +2138,11 @@ hif_pci_ce_send_done(struct CE_handle *copyeng, void *ce_context, * The upper layer callback will be triggered * when last fragment is complteted. */ - if (transfer_context != CE_SENDLIST_ITEM_CTXT) { - if (scn->target_status == TARGET_STATUS_RESET) { - - qdf_nbuf_unmap_single(scn->qdf_dev, - transfer_context, - QDF_DMA_TO_DEVICE); - qdf_nbuf_free(transfer_context); - } else - msg_callbacks->txCompletionHandler( - msg_callbacks->Context, - transfer_context, transfer_id, - toeplitz_hash_result); - } + if (transfer_context != CE_SENDLIST_ITEM_CTXT) + msg_callbacks->txCompletionHandler( + msg_callbacks->Context, + transfer_context, transfer_id, + toeplitz_hash_result); qdf_spin_lock_bh(&pipe_info->completion_freeq_lock); pipe_info->num_sends_allowed++; diff --git a/htc/htc.c b/htc/htc.c index 5354f96148..2a40fea64f 100644 --- a/htc/htc.c +++ b/htc/htc.c @@ -821,7 +821,7 @@ void htc_stop(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); int i; - HTC_ENDPOINT *pEndpoint; + HTC_ENDPOINT *endpoint; #ifdef RX_SG_SUPPORT qdf_nbuf_t netbuf; qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; @@ -832,12 +832,12 @@ void htc_stop(HTC_HANDLE HTCHandle) HTC_INFO("%s: endpoints cleanup\n", __func__); /* cleanup endpoints */ for (i = 0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->endpoint[i]; - htc_flush_rx_hold_queue(target, pEndpoint); - htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL); - if (pEndpoint->ul_is_polled) { - qdf_timer_stop(&pEndpoint->ul_poll_timer); - qdf_timer_free(&pEndpoint->ul_poll_timer); + endpoint = &target->endpoint[i]; + htc_flush_rx_hold_queue(target, endpoint); + htc_flush_endpoint_tx(target, endpoint, HTC_TX_PACKET_TAG_ALL); + if (endpoint->ul_is_polled) { + qdf_timer_stop(&endpoint->ul_poll_timer); + qdf_timer_free(&endpoint->ul_poll_timer); } } @@ -863,12 +863,18 @@ void htc_stop(HTC_HANDLE HTCHandle) * In SSR case, HTC tx completion callback for wmi will be blocked * by TARGET_STATUS_RESET and HTC packets will be left unfreed on * lookup queue. + * + * In case of target failing to send wmi_ready_event, the htc connect + * msg buffer will be left unmapped and not freed. So calling the + * completion handler for this buffer will handle this scenario. */ HTC_INFO("%s: flush endpoints Tx lookup queue\n", __func__); for (i = 0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->endpoint[i]; - if (pEndpoint->service_id == WMI_CONTROL_SVC) + endpoint = &target->endpoint[i]; + if (endpoint->service_id == WMI_CONTROL_SVC) htc_flush_endpoint_txlookupQ(target, i, false); + else if (endpoint->service_id == HTC_CTRL_RSVD_SVC) + htc_flush_endpoint_txlookupQ(target, i, true); } HTC_INFO("%s: resetting endpoints state\n", __func__); diff --git a/htc/htc_send.c b/htc/htc_send.c index 19a91149b4..45363cc50a 100644 --- a/htc/htc_send.c +++ b/htc/htc_send.c @@ -125,6 +125,15 @@ static void send_packet_completion(HTC_TARGET *target, HTC_PACKET *pPacket) restore_tx_packet(target, pPacket); + /* + * In case of SSR, we cannot call the upper layer completion + * callbacks, hence just free the nbuf and HTC packet here. + */ + if (hif_get_target_status(target->hif_dev)) { + htc_free_control_tx_packet(target, pPacket); + return; + } + /* do completion */ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("HTC calling ep %d send complete callback on packet %pK\n",