diff options
Diffstat (limited to 'drivers/soc')
-rw-r--r-- | drivers/soc/qcom/glink_smd_xprt.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/soc/qcom/glink_smd_xprt.c b/drivers/soc/qcom/glink_smd_xprt.c index 9936dc22400c..c0ed33ed2845 100644 --- a/drivers/soc/qcom/glink_smd_xprt.c +++ b/drivers/soc/qcom/glink_smd_xprt.c @@ -558,6 +558,24 @@ static void ssr_work_func(struct work_struct *work) } /** + * 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); |