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: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
This commit is contained in:
Alex Elder 2014-11-17 08:08:40 -06:00 committed by Greg Kroah-Hartman
parent 78496db012
commit c7d0f258fb
2 changed files with 18 additions and 4 deletions

View file

@ -274,6 +274,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
operation->callback = NULL; /* set at submit time */
init_completion(&operation->completion);
INIT_DELAYED_WORK(&operation->timeout_work, operation_timeout);
kref_init(&operation->kref);
spin_lock_irq(&gb_operations_lock);
list_add_tail(&operation->links, &connection->operations);
@ -292,10 +293,11 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
/*
* 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))
return;
struct gb_operation *operation;
operation = container_of(kref, struct gb_operation, kref);
/* XXX Make sure it's not in flight */
spin_lock_irq(&gb_operations_lock);
@ -308,6 +310,12 @@ void gb_operation_destroy(struct gb_operation *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
* any payload so the request message is ready to go. If non-null,

View file

@ -65,6 +65,7 @@ struct gb_operation {
struct completion completion; /* Used if no callback */
struct delayed_work timeout_work;
struct kref kref;
struct list_head links; /* connection->{operations,pending} */
/* These are what's used by caller */
@ -78,7 +79,12 @@ void gb_connection_operation_recv(struct gb_connection *connection,
struct gb_operation *gb_operation_create(struct gb_connection *connection,
u8 type, size_t request_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,
gb_operation_callback callback);