msm: ipa3: fix send_cmd_timeout logic
When sending commands to IPA with timeout, the completion object needs to be allocated on heap to make sure memory is still available when EOT is received for this command. Change-Id: I0228967ca3b33a56489a80833c0565ba2dfe8c2a CRs-Fixed: 1082708 Acked-by: Ady Abraham <adya@qti.qualcomm.com> Signed-off-by: Skylar Chang <chiaweic@codeaurora.org>
This commit is contained in:
parent
ce610f2fc9
commit
d402048fac
1 changed files with 102 additions and 25 deletions
|
@ -766,6 +766,30 @@ static void ipa3_transport_irq_cmd_ack(void *user1, int user2)
|
|||
complete(&desc->xfer_done);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_transport_irq_cmd_ack_free - callback function which will be
|
||||
* called by SPS/GSI driver after an immediate command is complete.
|
||||
* This function will also free the completion object once it is done.
|
||||
* @tag_comp: pointer to the completion object
|
||||
* @ignored: parameter not used
|
||||
*
|
||||
* Complete the immediate commands completion object, this will release the
|
||||
* thread which waits on this completion object (ipa3_send_cmd())
|
||||
*/
|
||||
static void ipa3_transport_irq_cmd_ack_free(void *tag_comp, int ignored)
|
||||
{
|
||||
struct ipa3_tag_completion *comp = tag_comp;
|
||||
|
||||
if (!comp) {
|
||||
IPAERR("comp is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
complete(&comp->comp);
|
||||
if (atomic_dec_return(&comp->cnt) == 0)
|
||||
kfree(comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_send_cmd - send immediate commands
|
||||
* @num_desc: number of descriptors within the desc struct
|
||||
|
@ -778,7 +802,58 @@ static void ipa3_transport_irq_cmd_ack(void *user1, int user2)
|
|||
*/
|
||||
int ipa3_send_cmd(u16 num_desc, struct ipa3_desc *descr)
|
||||
{
|
||||
return ipa3_send_cmd_timeout(num_desc, descr, 0);
|
||||
struct ipa3_desc *desc;
|
||||
int i, result = 0;
|
||||
struct ipa3_sys_context *sys;
|
||||
int ep_idx;
|
||||
|
||||
for (i = 0; i < num_desc; i++)
|
||||
IPADBG("sending imm cmd %d\n", descr[i].opcode);
|
||||
|
||||
ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_CMD_PROD);
|
||||
if (-1 == ep_idx) {
|
||||
IPAERR("Client %u is not mapped\n",
|
||||
IPA_CLIENT_APPS_CMD_PROD);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
sys = ipa3_ctx->ep[ep_idx].sys;
|
||||
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
||||
|
||||
if (num_desc == 1) {
|
||||
init_completion(&descr->xfer_done);
|
||||
|
||||
if (descr->callback || descr->user1)
|
||||
WARN_ON(1);
|
||||
|
||||
descr->callback = ipa3_transport_irq_cmd_ack;
|
||||
descr->user1 = descr;
|
||||
if (ipa3_send_one(sys, descr, true)) {
|
||||
IPAERR("fail to send immediate command\n");
|
||||
result = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
wait_for_completion(&descr->xfer_done);
|
||||
} else {
|
||||
desc = &descr[num_desc - 1];
|
||||
init_completion(&desc->xfer_done);
|
||||
|
||||
if (desc->callback || desc->user1)
|
||||
WARN_ON(1);
|
||||
|
||||
desc->callback = ipa3_transport_irq_cmd_ack;
|
||||
desc->user1 = desc;
|
||||
if (ipa3_send(sys, num_desc, descr, true)) {
|
||||
IPAERR("fail to send multiple immediate command set\n");
|
||||
result = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
wait_for_completion(&desc->xfer_done);
|
||||
}
|
||||
|
||||
bail:
|
||||
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -800,6 +875,7 @@ int ipa3_send_cmd_timeout(u16 num_desc, struct ipa3_desc *descr, u32 timeout)
|
|||
struct ipa3_sys_context *sys;
|
||||
int ep_idx;
|
||||
int completed;
|
||||
struct ipa3_tag_completion *comp;
|
||||
|
||||
for (i = 0; i < num_desc; i++)
|
||||
IPADBG("sending imm cmd %d\n", descr[i].opcode);
|
||||
|
@ -810,55 +886,56 @@ int ipa3_send_cmd_timeout(u16 num_desc, struct ipa3_desc *descr, u32 timeout)
|
|||
IPA_CLIENT_APPS_CMD_PROD);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
comp = kzalloc(sizeof(*comp), GFP_ATOMIC);
|
||||
if (!comp) {
|
||||
IPAERR("no mem\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
init_completion(&comp->comp);
|
||||
|
||||
/* completion needs to be released from both here and in ack callback */
|
||||
atomic_set(&comp->cnt, 2);
|
||||
|
||||
sys = ipa3_ctx->ep[ep_idx].sys;
|
||||
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
||||
|
||||
if (num_desc == 1) {
|
||||
init_completion(&descr->xfer_done);
|
||||
|
||||
if (descr->callback || descr->user1)
|
||||
WARN_ON(1);
|
||||
|
||||
descr->callback = ipa3_transport_irq_cmd_ack;
|
||||
descr->user1 = descr;
|
||||
descr->callback = ipa3_transport_irq_cmd_ack_free;
|
||||
descr->user1 = comp;
|
||||
if (ipa3_send_one(sys, descr, true)) {
|
||||
IPAERR("fail to send immediate command\n");
|
||||
kfree(comp);
|
||||
result = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
if (timeout) {
|
||||
completed = wait_for_completion_timeout(
|
||||
&descr->xfer_done, msecs_to_jiffies(timeout));
|
||||
if (!completed)
|
||||
IPADBG("timeout waiting for imm-cmd ACK\n");
|
||||
} else {
|
||||
wait_for_completion(&descr->xfer_done);
|
||||
}
|
||||
} else {
|
||||
desc = &descr[num_desc - 1];
|
||||
init_completion(&desc->xfer_done);
|
||||
|
||||
if (desc->callback || desc->user1)
|
||||
WARN_ON(1);
|
||||
|
||||
desc->callback = ipa3_transport_irq_cmd_ack;
|
||||
desc->user1 = desc;
|
||||
desc->callback = ipa3_transport_irq_cmd_ack_free;
|
||||
desc->user1 = comp;
|
||||
if (ipa3_send(sys, num_desc, descr, true)) {
|
||||
IPAERR("fail to send multiple immediate command set\n");
|
||||
kfree(comp);
|
||||
result = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
if (timeout) {
|
||||
completed = wait_for_completion_timeout(
|
||||
&desc->xfer_done, msecs_to_jiffies(timeout));
|
||||
if (!completed)
|
||||
IPADBG("timeout waiting for imm-cmd ACK\n");
|
||||
} else {
|
||||
wait_for_completion(&desc->xfer_done);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
completed = wait_for_completion_timeout(
|
||||
&comp->comp, msecs_to_jiffies(timeout));
|
||||
if (!completed)
|
||||
IPADBG("timeout waiting for imm-cmd ACK\n");
|
||||
|
||||
if (atomic_dec_return(&comp->cnt) == 0)
|
||||
kfree(comp);
|
||||
|
||||
bail:
|
||||
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
||||
return result;
|
||||
|
|
Loading…
Add table
Reference in a new issue