Commit 5a3be769 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

greybus: operation: split incoming and outgoing cancellation

Split incoming and outgoing operation-cancellation helpers.

Incoming operations are only cancelled as part of connection tear down
and is specifically not needed in the driver API.
Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 0eb8c115
...@@ -238,7 +238,11 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, ...@@ -238,7 +238,11 @@ static void gb_connection_cancel_operations(struct gb_connection *connection,
gb_operation_get(operation); gb_operation_get(operation);
spin_unlock_irq(&connection->lock); spin_unlock_irq(&connection->lock);
gb_operation_cancel(operation, errno); if (gb_operation_is_incoming(operation))
gb_operation_cancel_incoming(operation, errno);
else
gb_operation_cancel(operation, errno);
gb_operation_put(operation); gb_operation_put(operation);
spin_lock_irq(&connection->lock); spin_lock_irq(&connection->lock);
......
...@@ -922,26 +922,17 @@ void gb_connection_recv(struct gb_connection *connection, ...@@ -922,26 +922,17 @@ void gb_connection_recv(struct gb_connection *connection,
} }
/* /*
* Cancel an operation synchronously, and record the given error to indicate * Cancel an outgoing operation synchronously, and record the given error to
* why. * indicate why.
*/ */
void gb_operation_cancel(struct gb_operation *operation, int errno) void gb_operation_cancel(struct gb_operation *operation, int errno)
{ {
if (gb_operation_is_incoming(operation)) { if (WARN_ON(gb_operation_is_incoming(operation)))
if (!gb_operation_is_unidirectional(operation)) { return;
/*
* Make sure the request handler has submitted the if (gb_operation_result_set(operation, errno)) {
* response before cancelling it. gb_message_cancel(operation->request);
*/ queue_work(gb_operation_workqueue, &operation->work);
flush_work(&operation->work);
if (!gb_operation_result_set(operation, errno))
gb_message_cancel(operation->response);
}
} else {
if (gb_operation_result_set(operation, errno)) {
gb_message_cancel(operation->request);
queue_work(gb_operation_workqueue, &operation->work);
}
} }
atomic_inc(&operation->waiters); atomic_inc(&operation->waiters);
...@@ -951,6 +942,31 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) ...@@ -951,6 +942,31 @@ void gb_operation_cancel(struct gb_operation *operation, int errno)
} }
EXPORT_SYMBOL_GPL(gb_operation_cancel); EXPORT_SYMBOL_GPL(gb_operation_cancel);
/*
* Cancel an incoming operation synchronously. Called during connection tear
* down.
*/
void gb_operation_cancel_incoming(struct gb_operation *operation, int errno)
{
if (WARN_ON(!gb_operation_is_incoming(operation)))
return;
if (!gb_operation_is_unidirectional(operation)) {
/*
* Make sure the request handler has submitted the response
* before cancelling it.
*/
flush_work(&operation->work);
if (!gb_operation_result_set(operation, errno))
gb_message_cancel(operation->response);
}
atomic_inc(&operation->waiters);
wait_event(gb_operation_cancellation_queue,
!gb_operation_is_active(operation));
atomic_dec(&operation->waiters);
}
/** /**
* gb_operation_sync: implement a "simple" synchronous gb operation. * gb_operation_sync: implement a "simple" synchronous gb operation.
* @connection: the Greybus connection to send this to * @connection: the Greybus connection to send this to
......
...@@ -171,6 +171,7 @@ int gb_operation_request_send(struct gb_operation *operation, ...@@ -171,6 +171,7 @@ int gb_operation_request_send(struct gb_operation *operation,
int gb_operation_request_send_sync(struct gb_operation *operation); int gb_operation_request_send_sync(struct gb_operation *operation);
void gb_operation_cancel(struct gb_operation *operation, int errno); void gb_operation_cancel(struct gb_operation *operation, int errno);
void gb_operation_cancel_incoming(struct gb_operation *operation, int errno);
void greybus_message_sent(struct greybus_host_device *hd, void greybus_message_sent(struct greybus_host_device *hd,
struct gb_message *message, int status); struct gb_message *message, int status);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment