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 <adya@qti.qualcomm.com>
Signed-off-by: Skylar Chang <chiaweic@codeaurora.org>
This commit is contained in:
Skylar Chang 2017-04-24 10:05:05 -07:00
parent f1a10f1598
commit a3488e9398
2 changed files with 32 additions and 12 deletions

View file

@ -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();

View file

@ -3582,21 +3582,30 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl)
memset(&mem, 0, sizeof(mem));
for (i = 0; i < IPA_GSI_CHANNEL_STOP_MAX_RETRY; i++) {
IPADBG("Calling gsi_stop_channel\n");
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 returned %d\n", res);
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 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);
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 */