aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/connection.c
diff options
context:
space:
mode:
authorJohan Hovold <johan@hovoldconsulting.com>2016-05-27 17:26:37 +0200
committerGreg Kroah-Hartman <gregkh@google.com>2016-05-27 12:24:17 -0700
commit800d6c8f4e66cc6ff3737b4de1272c31cd9e1e3c (patch)
tree6fede458e5dbed9afe805213e863420c98d32ff0 /drivers/staging/greybus/connection.c
parentgreybus: connection: implement proper connection closure (diff)
downloadlinux-dev-800d6c8f4e66cc6ff3737b4de1272c31cd9e1e3c.tar.xz
linux-dev-800d6c8f4e66cc6ff3737b4de1272c31cd9e1e3c.zip
greybus: connection: add flush host-device callback
Add a new host-device callback to flush any host-device queues, including any ongoing transfers, as part of connection tear down. The host-device buffers are flushed after the disconnecting operation have completed and the AP queues have been emptied. This can be used to flush already queued messages which upon reception would have been discarded by the remote end anyway. Note that this does not remove the need to flush any host-device queues as part of CPort disable which needs to make the CPort ready for reuse after deallocating all associated state and resetting the port. Suggested-by: Mitchell Tasman <tasman@leaflabs.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/connection.c')
-rw-r--r--drivers/staging/greybus/connection.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c
index 77067515a28a..c1cdfcd830a4 100644
--- a/drivers/staging/greybus/connection.c
+++ b/drivers/staging/greybus/connection.c
@@ -302,6 +302,24 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection)
}
}
+static int gb_connection_hd_cport_flush(struct gb_connection *connection)
+{
+ struct gb_host_device *hd = connection->hd;
+ int ret;
+
+ if (!hd->driver->cport_flush)
+ return 0;
+
+ ret = hd->driver->cport_flush(hd, connection->hd_cport_id);
+ if (ret) {
+ dev_err(&hd->dev, "%s: failed to flush host cport: %d\n",
+ connection->name, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static int
gb_connection_hd_cport_features_enable(struct gb_connection *connection)
{
@@ -651,6 +669,9 @@ err_control_disconnecting:
gb_connection_cancel_operations(connection, -ESHUTDOWN);
spin_unlock_irq(&connection->lock);
+ /* Transmit queue should already be empty. */
+ gb_connection_hd_cport_flush(connection);
+
gb_connection_ping(connection);
gb_connection_hd_cport_features_disable(connection);
gb_connection_svc_connection_quiescing(connection);
@@ -736,6 +757,8 @@ void gb_connection_disable(struct gb_connection *connection)
gb_connection_cancel_operations(connection, -ESHUTDOWN);
spin_unlock_irq(&connection->lock);
+ gb_connection_hd_cport_flush(connection);
+
gb_connection_ping(connection);
gb_connection_hd_cport_features_disable(connection);
gb_connection_svc_connection_quiescing(connection);
@@ -766,6 +789,7 @@ void gb_connection_disable_forced(struct gb_connection *connection)
gb_connection_cancel_operations(connection, -ESHUTDOWN);
spin_unlock_irq(&connection->lock);
+ gb_connection_hd_cport_flush(connection);
gb_connection_hd_cport_features_disable(connection);
gb_connection_svc_connection_destroy(connection);
gb_connection_hd_cport_disable(connection);