From 5a3be769e92ea993f8a8c27b89571c276d874733 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:35 +0200 Subject: 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: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/connection.c | 6 ++++- drivers/staging/greybus/operation.c | 50 ++++++++++++++++++++++++------------ drivers/staging/greybus/operation.h | 1 + 3 files changed, 39 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ac9b2d174805..81a5df0e3230 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -238,7 +238,11 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, gb_operation_get(operation); 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); spin_lock_irq(&connection->lock); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0576f197f58e..17b07fb24006 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -922,26 +922,17 @@ void gb_connection_recv(struct gb_connection *connection, } /* - * Cancel an operation synchronously, and record the given error to indicate - * why. + * Cancel an outgoing operation synchronously, and record the given error to + * indicate why. */ void gb_operation_cancel(struct gb_operation *operation, int errno) { - if (gb_operation_is_incoming(operation)) { - 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); - } - } else { - if (gb_operation_result_set(operation, errno)) { - gb_message_cancel(operation->request); - queue_work(gb_operation_workqueue, &operation->work); - } + if (WARN_ON(gb_operation_is_incoming(operation))) + return; + + if (gb_operation_result_set(operation, errno)) { + gb_message_cancel(operation->request); + queue_work(gb_operation_workqueue, &operation->work); } atomic_inc(&operation->waiters); @@ -951,6 +942,31 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) } 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. * @connection: the Greybus connection to send this to diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 26ecd66710a3..d7e59a3f4b47 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -171,6 +171,7 @@ int gb_operation_request_send(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_incoming(struct gb_operation *operation, int errno); void greybus_message_sent(struct greybus_host_device *hd, struct gb_message *message, int status); -- cgit v1.2.3-55-g7522