greybus: add a reference to pending operations

Grab an extra reference to an operation before sending it.  Drop
that reference at the end of its completion handling.

It turns out gb_operation_get() got deleted along the way, so this
re-introduces it.  We're assuming we only get a reference when
there's at least one in existence so we don't need a semaphore to
protect it.  Emphasize this by *not* returning a pointer to
the referenced operation.

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-21 19:29:15 -06:00 committed by Greg Kroah-Hartman
parent 583c3117a4
commit deb4b9efb3
2 changed files with 18 additions and 5 deletions

View File

@ -157,6 +157,7 @@ static void gb_operation_complete(struct gb_operation *operation)
operation->callback(operation);
else
complete_all(&operation->completion);
gb_operation_put(operation);
}
/*
@ -409,6 +410,14 @@ gb_operation_create_incoming(struct gb_connection *connection,
request_size, response_size);
}
/*
* Get an additional reference on an operation.
*/
void gb_operation_get(struct gb_operation *operation)
{
kref_get(&operation->kref);
}
/*
* Destroy a previously created operation.
*/
@ -429,6 +438,10 @@ static void _gb_operation_destroy(struct kref *kref)
kmem_cache_free(gb_operation_cache, operation);
}
/*
* Drop a reference on an operation, and destroy it when the last
* one is gone.
*/
void gb_operation_put(struct gb_operation *operation)
{
if (!WARN_ON(!operation))
@ -454,11 +467,11 @@ int gb_operation_request_send(struct gb_operation *operation,
return -ENOTCONN;
/*
* XXX
* I think the order of operations is going to be
* significant, and if so, we may need a mutex to surround
* setting the operation id and submitting the buffer.
* First, get an extra reference on the operation.
* It'll be dropped when the operation completes.
*/
gb_operation_get(operation);
operation->callback = callback;
gb_pending_operation_insert(operation);

View File

@ -88,7 +88,7 @@ void gb_connection_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);
struct gb_operation *gb_operation_get(struct gb_operation *operation);
void 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)
{