greybus: operation: make the timeout a per-operation thing, not per-connection

An operation is what can timeout, not a connection itself.  So notify
the operation timedout, and the connection can then do with it as it
sees fit, if necessary.

Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c
index 9b889b1..736c2c1 100644
--- a/drivers/staging/greybus/operation.c
+++ b/drivers/staging/greybus/operation.c
@@ -19,7 +19,7 @@
  */
 #define GB_OPERATION_TYPE_RESPONSE	0x80
 
-#define CONNECTION_TIMEOUT_DEFAULT	1000	/* milliseconds */
+#define OPERATION_TIMEOUT_DEFAULT	1000	/* milliseconds */
 
 /*
  * XXX This needs to be coordinated with host driver parameters
@@ -105,29 +105,25 @@
 	rb_insert_color(node, root);
 	spin_unlock_irq(&gb_operations_lock);
 
-	timeout = msecs_to_jiffies(CONNECTION_TIMEOUT_DEFAULT);
+	timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT);
 	if (start_timer)
-		schedule_delayed_work(&connection->timeout_work, timeout);
+		schedule_delayed_work(&operation->timeout_work, timeout);
 	else
-		mod_delayed_work(system_wq, &connection->timeout_work, timeout);
+		mod_delayed_work(system_wq, &operation->timeout_work, timeout);
 }
 
 static void gb_operation_remove(struct gb_operation *operation)
 {
 	struct gb_connection *connection = operation->connection;
-	bool last_pending;
 
+	/* Shut down our timeout timer */
+	cancel_delayed_work(&operation->timeout_work);
+
+	/* Take us off of the list of pending operations */
 	spin_lock_irq(&gb_operations_lock);
 	rb_erase(&operation->node, &connection->pending);
-	last_pending = RB_EMPTY_ROOT(&connection->pending);
 	spin_unlock_irq(&gb_operations_lock);
 
-	/*
-	 * If there are no more pending requests, we can stop the
-	 * timeout timer.
-	 */
-	if (last_pending)
-		cancel_delayed_work(&connection->timeout_work);
 }
 
 static struct gb_operation *
@@ -159,7 +155,7 @@
  * any waiters.  Otherwise we assume calling the completion is enough
  * and nobody else will be waiting.
  */
-void gb_operation_complete(struct gb_operation *operation)
+static void gb_operation_complete(struct gb_operation *operation)
 {
 	if (operation->callback)
 		operation->callback(operation);
@@ -248,6 +244,24 @@
 }
 
 /*
+ * Timeout call for the operation.
+ *
+ * If this fires, something went wrong, so mark the result as timed out, and
+ * run the completion handler, which (hopefully) should clean up the operation
+ * properly.
+ */
+static void operation_timeout(struct work_struct *work)
+{
+	struct gb_operation *operation;
+
+	operation = container_of(work, struct gb_operation, timeout_work.work);
+	printk("timeout!\n");
+
+	operation->result = GB_OP_TIMEOUT;
+	gb_operation_complete(operation);
+}
+
+/*
  * Buffer completion function.  We get notified whenever any buffer
  * completes.  For outbound messages, this tells us that the message
  * has been sent.  For inbound messages, it means the data has
@@ -376,6 +390,7 @@
 	INIT_WORK(&operation->recv_work, gb_operation_recv_work);
 	operation->callback = NULL;	/* set at submit time */
 	init_completion(&operation->completion);
+	INIT_DELAYED_WORK(&operation->timeout_work, operation_timeout);
 
 	spin_lock_irq(&gb_operations_lock);
 	list_add_tail(&operation->links, &connection->operations);