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);
|
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
|
* process_tx_done() - process a tx done task
|
||||||
* @work: The tx done task to process.
|
* @work: The tx done task to process.
|
||||||
|
@ -899,6 +917,7 @@ static void smd_data_ch_close(struct channel *ch)
|
||||||
{
|
{
|
||||||
struct intent_info *intent;
|
struct intent_info *intent;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct channel_work *ch_work;
|
||||||
|
|
||||||
SMDXPRT_INFO(ch->edge, "%s Closing SMD channel lcid %u\n",
|
SMDXPRT_INFO(ch->edge, "%s Closing SMD channel lcid %u\n",
|
||||||
__func__, ch->lcid);
|
__func__, ch->lcid);
|
||||||
|
@ -919,11 +938,12 @@ static void smd_data_ch_close(struct channel *ch)
|
||||||
smd_close(ch->smd_ch);
|
smd_close(ch->smd_ch);
|
||||||
ch->smd_ch = NULL;
|
ch->smd_ch = NULL;
|
||||||
} else if (ch->local_legacy) {
|
} else if (ch->local_legacy) {
|
||||||
mutex_lock(&ch->edge->rx_cmd_lock);
|
ch_work = kzalloc(sizeof(*ch_work), GFP_KERNEL);
|
||||||
ch->edge->xprt_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
|
if (ch_work) {
|
||||||
&ch->edge->xprt_if,
|
ch_work->ch = ch;
|
||||||
ch->lcid);
|
INIT_WORK(&ch_work->work, deferred_close_ack);
|
||||||
mutex_unlock(&ch->edge->rx_cmd_lock);
|
queue_work(ch->wq, &ch_work->work);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&ch->ch_probe_lock);
|
mutex_unlock(&ch->ch_probe_lock);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue