spcom: always wait for glink LOCAL_DISCONNECT event after glink_close()

Wait for glink LOCAL_DISCONNECT event, even if the channel is not
connected.

Change-Id: I03f20b6dbb2f46d7abd6996e8d298e991cf3f82b
Signed-off-by: Amir Samuelov <amirs@codeaurora.org>
This commit is contained in:
Amir Samuelov 2017-04-06 17:28:22 +03:00 committed by Gerrit - the friendly Code Review server
parent 6cf6835d96
commit cefed44f00

View file

@ -463,8 +463,7 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
switch (event) { switch (event) {
case GLINK_CONNECTED: case GLINK_CONNECTED:
pr_debug("GLINK_CONNECTED, ch name [%s].\n", ch->name); pr_debug("GLINK_CONNECTED, ch name [%s].\n", ch->name);
complete_all(&ch->connect); ch->glink_state = event;
/* /*
* if spcom_notify_state() is called within glink_open() * if spcom_notify_state() is called within glink_open()
* then ch->glink_handle is not updated yet. * then ch->glink_handle is not updated yet.
@ -484,6 +483,7 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
ch->rx_buf_size); ch->rx_buf_size);
ch->rx_buf_ready = true; ch->rx_buf_ready = true;
} }
complete_all(&ch->connect);
break; break;
case GLINK_LOCAL_DISCONNECTED: case GLINK_LOCAL_DISCONNECTED:
/* /*
@ -491,6 +491,7 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
* only after *both* sides closed the channel. * only after *both* sides closed the channel.
*/ */
pr_debug("GLINK_LOCAL_DISCONNECTED, ch [%s].\n", ch->name); pr_debug("GLINK_LOCAL_DISCONNECTED, ch [%s].\n", ch->name);
ch->glink_state = event;
complete_all(&ch->disconnect); complete_all(&ch->disconnect);
break; break;
case GLINK_REMOTE_DISCONNECTED: case GLINK_REMOTE_DISCONNECTED:
@ -501,6 +502,8 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
*/ */
pr_err("GLINK_REMOTE_DISCONNECTED, ch [%s].\n", ch->name); pr_err("GLINK_REMOTE_DISCONNECTED, ch [%s].\n", ch->name);
ch->glink_state = event;
/* /*
* Abort any blocking read() operation. * Abort any blocking read() operation.
* The glink notification might be after REMOTE_DISCONNECT. * The glink notification might be after REMOTE_DISCONNECT.
@ -518,8 +521,6 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
(int) event, ch->name); (int) event, ch->name);
return; return;
} }
ch->glink_state = event;
} }
/** /**
@ -2132,7 +2133,6 @@ static int spcom_device_release(struct inode *inode, struct file *filp)
{ {
struct spcom_channel *ch; struct spcom_channel *ch;
const char *name = file_to_filename(filp); const char *name = file_to_filename(filp);
bool connected = false;
pr_debug("Close file [%s].\n", name); pr_debug("Close file [%s].\n", name);
@ -2154,19 +2154,18 @@ static int spcom_device_release(struct inode *inode, struct file *filp)
} }
/* channel might be already closed or disconnected */ /* channel might be already closed or disconnected */
if (spcom_is_channel_open(ch) && spcom_is_channel_connected(ch)) if (!spcom_is_channel_open(ch)) {
connected = true; pr_err("ch [%s] already closed.\n", name);
return 0;
}
reinit_completion(&ch->disconnect); reinit_completion(&ch->disconnect);
spcom_close(ch); spcom_close(ch);
if (connected) { pr_debug("Wait for event GLINK_LOCAL_DISCONNECTED, ch [%s].\n", name);
pr_debug("Wait for event GLINK_LOCAL_DISCONNECTED, ch [%s].\n", wait_for_completion(&ch->disconnect);
name); pr_debug("GLINK_LOCAL_DISCONNECTED signaled, ch [%s].\n", name);
wait_for_completion(&ch->disconnect);
pr_debug("GLINK_LOCAL_DISCONNECTED signaled, ch [%s].\n", name);
}
return 0; return 0;
} }