soc: qcom: glink_smd_xprt: Defer channel close ACK operation
Depending on the timing of two competing transport registration with G-Link core, a channel gets opened on one transport and then immediately migrated to another transport. This channel migration happens in the context of glink_open() operation itself and causes a re-lock attempt on an already locked mutex. Defer the channel close ACK operation so that channel migration does not hit the deadlock. CRs-Fixed: 1004150 Change-Id: I188846b95369b674830bc01ddeca764ad6d4d391 Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
This commit is contained in:
parent
1071415ec4
commit
2eabbd25b6
1 changed files with 25 additions and 5 deletions
|
@ -557,6 +557,24 @@ static void ssr_work_func(struct work_struct *work)
|
|||
mutex_unlock(&einfo->in_ssr_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* deferred_close_ack() - Generate a deferred channel close ack
|
||||
* @work: The channel close ack work to generate.
|
||||
*/
|
||||
static void deferred_close_ack(struct work_struct *work)
|
||||
{
|
||||
struct channel_work *ch_work;
|
||||
struct channel *ch;
|
||||
|
||||
ch_work = container_of(work, struct channel_work, work);
|
||||
ch = ch_work->ch;
|
||||
mutex_lock(&ch->edge->rx_cmd_lock);
|
||||
ch->edge->xprt_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
|
||||
&ch->edge->xprt_if, ch->lcid);
|
||||
mutex_unlock(&ch->edge->rx_cmd_lock);
|
||||
kfree(ch_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* process_tx_done() - process a tx done task
|
||||
* @work: The tx done task to process.
|
||||
|
@ -899,6 +917,7 @@ static void smd_data_ch_close(struct channel *ch)
|
|||
{
|
||||
struct intent_info *intent;
|
||||
unsigned long flags;
|
||||
struct channel_work *ch_work;
|
||||
|
||||
SMDXPRT_INFO(ch->edge, "%s Closing SMD channel lcid %u\n",
|
||||
__func__, ch->lcid);
|
||||
|
@ -919,11 +938,12 @@ static void smd_data_ch_close(struct channel *ch)
|
|||
smd_close(ch->smd_ch);
|
||||
ch->smd_ch = NULL;
|
||||
} else if (ch->local_legacy) {
|
||||
mutex_lock(&ch->edge->rx_cmd_lock);
|
||||
ch->edge->xprt_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
|
||||
&ch->edge->xprt_if,
|
||||
ch->lcid);
|
||||
mutex_unlock(&ch->edge->rx_cmd_lock);
|
||||
ch_work = kzalloc(sizeof(*ch_work), GFP_KERNEL);
|
||||
if (ch_work) {
|
||||
ch_work->ch = ch;
|
||||
INIT_WORK(&ch_work->work, deferred_close_ack);
|
||||
queue_work(ch->wq, &ch_work->work);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ch->ch_probe_lock);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue