greybus: introduce gb_operation_request_send_sync()

Define a new function used to initiate a synchronous operation.
It sends the operation request message and doesn't return until
the response has been received and/or the operation's result
has been set.

This gets rid of the convention that a null callback pointer
signifies a synchronous operation.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c
index 19a7df9..bd1bada 100644
--- a/drivers/staging/greybus/i2c-gb.c
+++ b/drivers/staging/greybus/i2c-gb.c
@@ -285,7 +285,7 @@
 		return -ENOMEM;
 
 	/* Synchronous operation--no callback */
-	ret = gb_operation_request_send(operation, NULL);
+	ret = gb_operation_request_send_sync(operation);
 	if (ret) {
 		if (ret != -EAGAIN)
 			pr_err("transfer operation failed (%d)\n", ret);
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c
index 15a6e3b..c62f200 100644
--- a/drivers/staging/greybus/operation.c
+++ b/drivers/staging/greybus/operation.c
@@ -641,7 +641,6 @@
 	struct gb_operation_msg_hdr *header;
 	unsigned long timeout;
 	unsigned int cycle;
-	int ret;
 
 	if (connection->state != GB_CONNECTION_STATE_ENABLED)
 		return -ENOTCONN;
@@ -652,11 +651,12 @@
 	 */
 	gb_operation_get(operation);
 
-	/* A null callback pointer means synchronous return */
-	if (callback)
-		operation->callback = callback;
-	else
-		operation->callback = gb_operation_sync_callback;
+	/*
+	 * Record the callback function, which is executed in
+	 * non-atomic (workqueue) context when the final result
+	 * of an operation has been set.
+	 */
+	operation->callback = callback;
 
 	/*
 	 * Assign the operation's id, and store it in the request header.
@@ -677,8 +677,22 @@
 
 	/* All set, send the request */
 	gb_operation_result_set(operation, -EINPROGRESS);
-	ret = gb_message_send(operation->request);
-	if (ret || callback)
+
+	return gb_message_send(operation->request);
+}
+
+/*
+ * Send a synchronous operation.  This function is expected to
+ * block, returning only when the response has arrived, (or when an
+ * error is detected.  The return value is the result of the
+ * operation.
+ */
+int gb_operation_request_send_sync(struct gb_operation *operation)
+{
+	int ret;
+
+	ret = gb_operation_request_send(operation, gb_operation_sync_callback);
+	if (ret)
 		return ret;
 
 	/* Cancel the operation if interrupted */
@@ -923,8 +937,7 @@
 	if (request_size)
 		memcpy(operation->request->payload, request, request_size);
 
-	/* Synchronous operation--no callback */
-	ret = gb_operation_request_send(operation, NULL);
+	ret = gb_operation_request_send_sync(operation);
 	if (ret)
 		pr_err("version operation failed (%d)\n", ret);
 	else
diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h
index c73d9b9..3415e8b 100644
--- a/drivers/staging/greybus/operation.h
+++ b/drivers/staging/greybus/operation.h
@@ -115,6 +115,7 @@
 
 int gb_operation_request_send(struct gb_operation *operation,
 				gb_operation_callback callback);
+int gb_operation_request_send_sync(struct gb_operation *operation);
 int gb_operation_response_send(struct gb_operation *operation, int errno);
 
 void gb_operation_cancel(struct gb_operation *operation, int errno);
diff --git a/drivers/staging/greybus/usb-gb.c b/drivers/staging/greybus/usb-gb.c
index ab4e093..e5da72a 100644
--- a/drivers/staging/greybus/usb-gb.c
+++ b/drivers/staging/greybus/usb-gb.c
@@ -169,7 +169,7 @@
 	memcpy(&request->payload, urb->transfer_buffer,
 	       urb->transfer_buffer_length);
 
-	ret = gb_operation_request_send(operation, NULL);
+	ret = gb_operation_request_send_sync(operation);
 	gb_operation_destroy(operation);
 
 	return ret;