greybus: reference count operations
authorAlex Elder <elder@linaro.org>
Mon, 17 Nov 2014 14:08:40 +0000 (08:08 -0600)
committerGreg Kroah-Hartman <greg@kroah.com>
Mon, 17 Nov 2014 18:41:19 +0000 (10:41 -0800)
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>
drivers/staging/greybus/operation.c
drivers/staging/greybus/operation.h

index bc68a5f9be667d84c64004723ef560c61960faff..2b33d336bfad9e9718cb4d329abd71deea1bbc51 100644 (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 @@ err_cache:
 /*
  * 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,
index f30b162f78b7739abbb76486757b413829dbe7de..dc15c2f61e30a1cf5a552e5a0744b389b34d9a2b 100644 (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);