From a3488e9398c42d1a9046c770c80ef3f81b527404 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Mon, 24 Apr 2017 10:05:05 -0700 Subject: [PATCH] msm: ipa3: fix channel stop retry logic Stopping a PROD channel might result in a timeout because the channel is not empty, or IPA is busy. Whether or not to retry a stop operation is determined by channel owner. This change removes the common retry logic of retrying to stop a PROD channel and adds a retry only for the scenario it is actually needed. Change-Id: I7ac1e81f7f99de2b0c3162aa5aaea2102a450838 CRs-Fixed: 2037955 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 13 ++++++++++++- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 29 +++++++++++++++++++---------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index c5b56f16788a..f23062702f28 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -1515,6 +1515,7 @@ int ipa3_teardown_sys_pipe(u32 clnt_hdl) struct ipa3_ep_context *ep; int empty; int result; + int i; if (clnt_hdl >= ipa3_ctx->ipa_num_pipes || ipa3_ctx->ep[clnt_hdl].valid == 0) { @@ -1551,7 +1552,17 @@ int ipa3_teardown_sys_pipe(u32 clnt_hdl) cancel_delayed_work_sync(&ep->sys->replenish_rx_work); flush_workqueue(ep->sys->wq); if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) { - result = ipa3_stop_gsi_channel(clnt_hdl); + /* channel stop might fail on timeout if IPA is busy */ + for (i = 0; i < IPA_GSI_CHANNEL_STOP_MAX_RETRY; i++) { + result = ipa3_stop_gsi_channel(clnt_hdl); + if (result == GSI_STATUS_SUCCESS) + break; + + if (result != -GSI_STATUS_AGAIN && + result != -GSI_STATUS_TIMED_OUT) + break; + } + if (result != GSI_STATUS_SUCCESS) { IPAERR("GSI stop chan err: %d.\n", result); BUG(); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index f4a7319ca290..5ffc1f23f47c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -3582,21 +3582,30 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl) memset(&mem, 0, sizeof(mem)); + if (IPA_CLIENT_IS_PROD(ep->client)) { + IPADBG("Calling gsi_stop_channel ch:%lu\n", + ep->gsi_chan_hdl); + res = gsi_stop_channel(ep->gsi_chan_hdl); + IPADBG("gsi_stop_channel ch: %lu returned %d\n", + ep->gsi_chan_hdl, res); + goto end_sequence; + } + for (i = 0; i < IPA_GSI_CHANNEL_STOP_MAX_RETRY; i++) { - IPADBG("Calling gsi_stop_channel\n"); + IPADBG("Calling gsi_stop_channel ch:%lu\n", + ep->gsi_chan_hdl); res = gsi_stop_channel(ep->gsi_chan_hdl); - IPADBG("gsi_stop_channel returned %d\n", res); + IPADBG("gsi_stop_channel ch: %lu returned %d\n", + ep->gsi_chan_hdl, res); if (res != -GSI_STATUS_AGAIN && res != -GSI_STATUS_TIMED_OUT) goto end_sequence; - if (IPA_CLIENT_IS_CONS(ep->client)) { - IPADBG("Inject a DMA_TASK with 1B packet to IPA\n"); - /* Send a 1B packet DMA_TASK to IPA and try again */ - res = ipa3_inject_dma_task_for_gsi(); - if (res) { - IPAERR("Failed to inject DMA TASk for GSI\n"); - goto end_sequence; - } + IPADBG("Inject a DMA_TASK with 1B packet to IPA\n"); + /* Send a 1B packet DMA_TASK to IPA and try again */ + res = ipa3_inject_dma_task_for_gsi(); + if (res) { + IPAERR("Failed to inject DMA TASk for GSI\n"); + goto end_sequence; } /* sleep for short period to flush IPA */ -- 2.11.0