greybus: define operation_cancel()
authorAlex Elder <elder@linaro.org>
Wed, 22 Oct 2014 07:04:29 +0000 (02:04 -0500)
committerGreg Kroah-Hartman <greg@kroah.com>
Wed, 22 Oct 2014 09:20:28 +0000 (17:20 +0800)
Define a new function operation_cancel() that cancels an
outstanding operation.  Use it to clear out any operations that
might be pending at the time a connection is torn down.

Note:  This code isn't really functional yet, partially because
greybus_kill_gbuf() is not implemented.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
drivers/staging/greybus/connection.c
drivers/staging/greybus/operation.c
drivers/staging/greybus/operation.h

index 368f056..9bcda99 100644 (file)
@@ -162,12 +162,19 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
  */
 void gb_connection_destroy(struct gb_connection *connection)
 {
+       struct gb_operation *operation;
+       struct gb_operation *next;
+
        if (WARN_ON(!connection))
                return;
 
        /* XXX Need to wait for any outstanding requests to complete */
        WARN_ON(!list_empty(&connection->operations));
 
+       list_for_each_entry_safe(operation, next, &connection->operations,
+                                       links) {
+               gb_operation_cancel(operation);
+       }
        spin_lock_irq(&gb_connections_lock);
        list_del(&connection->interface_links);
        _gb_hd_connection_remove(connection);
index e70e8a3..afb42d5 100644 (file)
@@ -501,6 +501,24 @@ void gb_connection_operation_recv(struct gb_connection *connection,
        queue_work(gb_operation_recv_workqueue, &operation->recv_work);
 }
 
+/*
+ * Cancel an operation.
+ */
+void gb_operation_cancel(struct gb_operation *operation)
+{
+       int ret;
+
+       operation->canceled = true;
+       ret = greybus_kill_gbuf(operation->request);
+       if (ret)
+               pr_warn("error %d killing request gbuf\n", ret);
+       if (operation->response) {
+               ret = greybus_kill_gbuf(operation->response);
+               if (ret)
+                       pr_warn("error %d killing response gbuf\n", ret);
+       }
+}
+
 int gb_operation_init(void)
 {
        gb_operation_cache = kmem_cache_create("gb_operation_cache",
index 59aad3a..1a8e6b9 100644 (file)
@@ -55,6 +55,7 @@ struct gb_operation {
        struct gbuf             *request;
        struct gbuf             *response;
        u16                     id;
+       bool                    canceled;
 
        u8                      result;
        struct work_struct      recv_work;
@@ -81,6 +82,7 @@ int gb_operation_request_send(struct gb_operation *operation,
                                gb_operation_callback callback);
 int gb_operation_response_send(struct gb_operation *operation);
 
+void gb_operation_cancel(struct gb_operation *operation);
 int gb_operation_wait(struct gb_operation *operation);
 void gb_operation_complete(struct gb_operation *operation);