Commit c7d0f258 authored by Alex Elder's avatar Alex Elder Committed by Greg Kroah-Hartman

greybus: reference count operations

Add a reference counter to the operations structure.  We'll
need this when operations are actually allowed to complete
asynchronously.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 78496db0
...@@ -274,6 +274,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, ...@@ -274,6 +274,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
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, operation_timeout);
kref_init(&operation->kref);
spin_lock_irq(&gb_operations_lock); spin_lock_irq(&gb_operations_lock);
list_add_tail(&operation->links, &connection->operations); list_add_tail(&operation->links, &connection->operations);
...@@ -292,10 +293,11 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, ...@@ -292,10 +293,11 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
/* /*
* Destroy a previously created operation. * Destroy a previously created operation.
*/ */
void gb_operation_destroy(struct gb_operation *operation) static void _gb_operation_destroy(struct kref *kref)
{ {
if (WARN_ON(!operation)) struct gb_operation *operation;
return;
operation = container_of(kref, struct gb_operation, kref);
/* XXX Make sure it's not in flight */ /* XXX Make sure it's not in flight */
spin_lock_irq(&gb_operations_lock); spin_lock_irq(&gb_operations_lock);
...@@ -308,6 +310,12 @@ void gb_operation_destroy(struct gb_operation *operation) ...@@ -308,6 +310,12 @@ void gb_operation_destroy(struct gb_operation *operation)
kmem_cache_free(gb_operation_cache, operation); kmem_cache_free(gb_operation_cache, operation);
} }
void gb_operation_put(struct gb_operation *operation)
{
if (!WARN_ON(!operation))
kref_put(&operation->kref, _gb_operation_destroy);
}
/* /*
* Send an operation request message. The caller has filled in * Send an operation request message. The caller has filled in
* any payload so the request message is ready to go. If non-null, * any payload so the request message is ready to go. If non-null,
......
...@@ -65,6 +65,7 @@ struct gb_operation { ...@@ -65,6 +65,7 @@ struct gb_operation {
struct completion completion; /* Used if no callback */ struct completion completion; /* Used if no callback */
struct delayed_work timeout_work; struct delayed_work timeout_work;
struct kref kref;
struct list_head links; /* connection->{operations,pending} */ struct list_head links; /* connection->{operations,pending} */
/* These are what's used by caller */ /* These are what's used by caller */
...@@ -78,7 +79,12 @@ void gb_connection_operation_recv(struct gb_connection *connection, ...@@ -78,7 +79,12 @@ void gb_connection_operation_recv(struct gb_connection *connection,
struct gb_operation *gb_operation_create(struct gb_connection *connection, struct gb_operation *gb_operation_create(struct gb_connection *connection,
u8 type, size_t request_size, u8 type, size_t request_size,
size_t response_size); size_t response_size);
void gb_operation_destroy(struct gb_operation *operation); struct gb_operation *gb_operation_get(struct gb_operation *operation);
void gb_operation_put(struct gb_operation *operation);
static inline void gb_operation_destroy(struct gb_operation *operation)
{
gb_operation_put(operation);
}
int gb_operation_request_send(struct gb_operation *operation, int gb_operation_request_send(struct gb_operation *operation,
gb_operation_callback callback); gb_operation_callback callback);
......
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