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);
/*
* 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);
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,
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 */
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);