Commit 701615f8 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

greybus: operation: add completion work queue

Add dedicated bound work queue for operation completions and use the
connection work queues for incoming requests only.

There is no need to keep responses ordered internally or with respect to
requests. Instead allow operations to complete as soon as possible when
a response arrives (or the operation is cancelled).

Note that this also allows synchronous requests to be submitted from
request handlers as responses will no longer be blocked on the same
single-threaded work queue. Similarly, operations can now also be
cancelled from a request handler.
Tested-by: default avatarRui Miguel Silva <rui.silva@linaro.org>
Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Reviewed-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 5a5bc354
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
static struct kmem_cache *gb_operation_cache; static struct kmem_cache *gb_operation_cache;
static struct kmem_cache *gb_message_cache; static struct kmem_cache *gb_message_cache;
/* Workqueue to handle Greybus operation completions. */
static struct workqueue_struct *gb_operation_completion_wq;
/* Wait queue for synchronous cancellations. */ /* Wait queue for synchronous cancellations. */
static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue); static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue);
...@@ -796,8 +799,10 @@ void greybus_message_sent(struct greybus_host_device *hd, ...@@ -796,8 +799,10 @@ void greybus_message_sent(struct greybus_host_device *hd,
gb_operation_put_active(operation); gb_operation_put_active(operation);
gb_operation_put(operation); gb_operation_put(operation);
} else if (status) { } else if (status) {
if (gb_operation_result_set(operation, status)) if (gb_operation_result_set(operation, status)) {
queue_work(connection->wq, &operation->work); queue_work(gb_operation_completion_wq,
&operation->work);
}
} }
} }
EXPORT_SYMBOL_GPL(greybus_message_sent); EXPORT_SYMBOL_GPL(greybus_message_sent);
...@@ -874,7 +879,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, ...@@ -874,7 +879,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
/* The rest will be handled in work queue context */ /* The rest will be handled in work queue context */
if (gb_operation_result_set(operation, errno)) { if (gb_operation_result_set(operation, errno)) {
memcpy(message->header, data, size); memcpy(message->header, data, size);
queue_work(connection->wq, &operation->work); queue_work(gb_operation_completion_wq, &operation->work);
} }
gb_operation_put(operation); gb_operation_put(operation);
...@@ -928,14 +933,12 @@ void gb_connection_recv(struct gb_connection *connection, ...@@ -928,14 +933,12 @@ void gb_connection_recv(struct gb_connection *connection,
*/ */
void gb_operation_cancel(struct gb_operation *operation, int errno) void gb_operation_cancel(struct gb_operation *operation, int errno)
{ {
struct gb_connection *connection = operation->connection;
if (WARN_ON(gb_operation_is_incoming(operation))) if (WARN_ON(gb_operation_is_incoming(operation)))
return; return;
if (gb_operation_result_set(operation, errno)) { if (gb_operation_result_set(operation, errno)) {
gb_message_cancel(operation->request); gb_message_cancel(operation->request);
queue_work(connection->wq, &operation->work); queue_work(gb_operation_completion_wq, &operation->work);
} }
atomic_inc(&operation->waiters); atomic_inc(&operation->waiters);
...@@ -1042,8 +1045,16 @@ int __init gb_operation_init(void) ...@@ -1042,8 +1045,16 @@ int __init gb_operation_init(void)
if (!gb_operation_cache) if (!gb_operation_cache)
goto err_destroy_message_cache; goto err_destroy_message_cache;
gb_operation_completion_wq = alloc_workqueue("greybus_completion",
0, 0);
if (!gb_operation_completion_wq)
goto err_destroy_operation_cache;
return 0; return 0;
err_destroy_operation_cache:
kmem_cache_destroy(gb_operation_cache);
gb_operation_cache = NULL;
err_destroy_message_cache: err_destroy_message_cache:
kmem_cache_destroy(gb_message_cache); kmem_cache_destroy(gb_message_cache);
gb_message_cache = NULL; gb_message_cache = NULL;
...@@ -1053,6 +1064,8 @@ int __init gb_operation_init(void) ...@@ -1053,6 +1064,8 @@ int __init gb_operation_init(void)
void gb_operation_exit(void) void gb_operation_exit(void)
{ {
destroy_workqueue(gb_operation_completion_wq);
gb_operation_completion_wq = NULL;
kmem_cache_destroy(gb_operation_cache); kmem_cache_destroy(gb_operation_cache);
gb_operation_cache = NULL; gb_operation_cache = NULL;
kmem_cache_destroy(gb_message_cache); kmem_cache_destroy(gb_message_cache);
......
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