From 90b10dc7003fae38c1a4c0dbf9df6266df9b47ad Mon Sep 17 00:00:00 2001 From: Amir Samuelov Date: Thu, 22 Dec 2016 13:06:48 +0200 Subject: [PATCH] spcom: abort any read() operation on SSR Abort any read() operation to unlock the channel mutex. On channel remote-disconnect notification, the local side should close the channel. However, open()/close()/read()/write() operations locks the channel mutex. The glink rx-abort notification happens only after the remote-disconnect notification, not as originally expected. Change-Id: I77f8e6de6f1b5c447a3516380c51db9c7129d2f3 Signed-off-by: Amir Samuelov --- drivers/soc/qcom/spcom.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index 5b3e6c36810e..e8ea99827403 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -272,6 +272,8 @@ static struct spcom_device *spcom_dev; static int spcom_create_channel_chardev(const char *name); static int spcom_open(struct spcom_channel *ch, unsigned int timeout_msec); static int spcom_close(struct spcom_channel *ch); +static void spcom_notify_rx_abort(void *handle, const void *priv, + const void *pkt_priv); /** * spcom_is_ready() - driver is initialized and ready. @@ -467,6 +469,13 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event) * This may happen upon remote SSR. */ pr_err("GLINK_REMOTE_DISCONNECTED, ch [%s].\n", ch->name); + + /* + * Abort any blocking read() operation. + * The glink notification might be after REMOTE_DISCONNECT. + */ + spcom_notify_rx_abort(NULL, ch, NULL); + /* * after glink_close(), * expecting notify GLINK_LOCAL_DISCONNECTED @@ -515,7 +524,7 @@ static void spcom_notify_rx_abort(void *handle, const void *priv, pr_debug("ch [%s] pending rx aborted.\n", ch->name); - if (spcom_is_channel_connected(ch)) { + if (spcom_is_channel_connected(ch) && (!ch->rx_abort)) { ch->rx_abort = true; complete_all(&ch->rx_done); } @@ -535,9 +544,9 @@ static void spcom_notify_tx_abort(void *handle, const void *priv, pr_debug("ch [%s] pending tx aborted.\n", ch->name); - if (spcom_is_channel_connected(ch)) { - complete_all(&ch->tx_done); + if (spcom_is_channel_connected(ch) && (!ch->tx_abort)) { ch->tx_abort = true; + complete_all(&ch->tx_done); } }