]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
greybus: add a reference to pending operations
authorAlex Elder <elder@linaro.org>
Sat, 22 Nov 2014 01:29:15 +0000 (19:29 -0600)
committerGreg Kroah-Hartman <greg@kroah.com>
Sat, 22 Nov 2014 03:36:42 +0000 (19:36 -0800)
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>
drivers/staging/greybus/operation.c
drivers/staging/greybus/operation.h

index 9ad714eb773cd3ff957b19e48bc3360a6e92f71f..ab27cd94880af5a5ff5cc804ee0c8dc034d6a480 100644 (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);
 
index f60884455f4b6760d6cbb7526d7197ed4024c977..befce156aa67a0e16dd5538744e809f04abae40a 100644 (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)
 {