From f68c05c0216e09ed93b12894747d8583dc5b8f8e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:17 -0600 Subject: [PATCH] greybus: cancel operation on timeout If an operation times out, we need to cancel whatever message it has in-flight. Do that instead of completing the operation, in the timeout handler. When the in-flight request message is canceled its completion function will lead to the proper completion of the operation. Change gb_operation_cancel() so it takes the errno that it's supposed to assign as the result of the operation. Note that we want to preserve the original -ETIMEDOUT error, so don't overwrite the operation result value if it has already been set. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/connection.c | 2 +- drivers/staging/greybus/operation.c | 19 ++++++------------- drivers/staging/greybus/operation.h | 3 +-- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 8cb2af37c25b..6503546ccc01 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -212,7 +212,7 @@ void gb_connection_destroy(struct gb_connection *connection) if (WARN_ON(!list_empty(&connection->operations))) { list_for_each_entry_safe(operation, next, &connection->operations, links) - gb_operation_cancel(operation); + gb_operation_cancel(operation, -ESHUTDOWN); } spin_lock_irq(&gb_connections_lock); list_del(&connection->interface_links); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 32cd2358ab1c..dc12e6df043d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -215,20 +215,13 @@ static void gb_operation_work(struct work_struct *work) /* * Timeout call for the operation. - * - * If this fires, something went wrong, so mark the result as timed out, and - * run the completion handler, which (hopefully) should clean up the operation - * properly. */ -static void operation_timeout(struct work_struct *work) +static void gb_operation_timeout(struct work_struct *work) { struct gb_operation *operation; operation = container_of(work, struct gb_operation, timeout_work.work); - pr_debug("%s: timeout!\n", __func__); - - operation->errno = -ETIMEDOUT; - gb_operation_complete(operation); + gb_operation_cancel(operation, -ETIMEDOUT); } /* @@ -376,7 +369,7 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing, INIT_WORK(&operation->work, gb_operation_work); operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); - INIT_DELAYED_WORK(&operation->timeout_work, operation_timeout); + INIT_DELAYED_WORK(&operation->timeout_work, gb_operation_timeout); kref_init(&operation->kref); spin_lock_irq(&gb_operations_lock); @@ -633,11 +626,11 @@ void gb_connection_recv(struct gb_connection *connection, } /* - * Cancel an operation. + * Cancel an operation, and record the given error to indicate why. */ -void gb_operation_cancel(struct gb_operation *operation) +void gb_operation_cancel(struct gb_operation *operation, int errno) { - operation->canceled = true; + operation->errno = errno; gb_message_cancel(operation->request); gb_message_cancel(operation->response); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index befce156aa67..d24e5e0d18f0 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -69,7 +69,6 @@ struct gb_operation { struct gb_message *request; struct gb_message *response; u16 id; - bool canceled; int errno; /* Operation result */ @@ -99,7 +98,7 @@ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback); int gb_operation_response_send(struct gb_operation *operation); -void gb_operation_cancel(struct gb_operation *operation); +void gb_operation_cancel(struct gb_operation *operation, int errno); int gb_operation_wait(struct gb_operation *operation); int gb_operation_status_map(u8 status);