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 <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
This commit is contained in:
parent
0e3d0e8fad
commit
f68c05c021
|
@ -212,7 +212,7 @@ void gb_connection_destroy(struct gb_connection *connection)
|
||||||
if (WARN_ON(!list_empty(&connection->operations))) {
|
if (WARN_ON(!list_empty(&connection->operations))) {
|
||||||
list_for_each_entry_safe(operation, next,
|
list_for_each_entry_safe(operation, next,
|
||||||
&connection->operations, links)
|
&connection->operations, links)
|
||||||
gb_operation_cancel(operation);
|
gb_operation_cancel(operation, -ESHUTDOWN);
|
||||||
}
|
}
|
||||||
spin_lock_irq(&gb_connections_lock);
|
spin_lock_irq(&gb_connections_lock);
|
||||||
list_del(&connection->interface_links);
|
list_del(&connection->interface_links);
|
||||||
|
|
|
@ -215,20 +215,13 @@ static void gb_operation_work(struct work_struct *work)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Timeout call for the operation.
|
* 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;
|
struct gb_operation *operation;
|
||||||
|
|
||||||
operation = container_of(work, struct gb_operation, timeout_work.work);
|
operation = container_of(work, struct gb_operation, timeout_work.work);
|
||||||
pr_debug("%s: timeout!\n", __func__);
|
gb_operation_cancel(operation, -ETIMEDOUT);
|
||||||
|
|
||||||
operation->errno = -ETIMEDOUT;
|
|
||||||
gb_operation_complete(operation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -376,7 +369,7 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing,
|
||||||
INIT_WORK(&operation->work, gb_operation_work);
|
INIT_WORK(&operation->work, gb_operation_work);
|
||||||
operation->callback = NULL; /* set at submit time */
|
operation->callback = NULL; /* set at submit time */
|
||||||
init_completion(&operation->completion);
|
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);
|
kref_init(&operation->kref);
|
||||||
|
|
||||||
spin_lock_irq(&gb_operations_lock);
|
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->request);
|
||||||
gb_message_cancel(operation->response);
|
gb_message_cancel(operation->response);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,6 @@ struct gb_operation {
|
||||||
struct gb_message *request;
|
struct gb_message *request;
|
||||||
struct gb_message *response;
|
struct gb_message *response;
|
||||||
u16 id;
|
u16 id;
|
||||||
bool canceled;
|
|
||||||
|
|
||||||
int errno; /* Operation result */
|
int errno; /* Operation result */
|
||||||
|
|
||||||
|
@ -99,7 +98,7 @@ int gb_operation_request_send(struct gb_operation *operation,
|
||||||
gb_operation_callback callback);
|
gb_operation_callback callback);
|
||||||
int gb_operation_response_send(struct gb_operation *operation);
|
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_wait(struct gb_operation *operation);
|
||||||
|
|
||||||
int gb_operation_status_map(u8 status);
|
int gb_operation_status_map(u8 status);
|
||||||
|
|
Loading…
Reference in New Issue