greybus: define greybus_data_sent()

Define greybus_data_sent(), which is a callback the host driver
makes when a buffer send request has completed.  The main use for
this is to actively detect errors that can occur while sending.
(Something like this existed at one time and was removed.)

This also defines gb_hd_message_find(), which looks up a message
pointer associated with a buffer sent over a given host device.
This is now a pretty trival mapping.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c
index 8843643..f32c981 100644
--- a/drivers/staging/greybus/es1-ap-usb.c
+++ b/drivers/staging/greybus/es1-ap-usb.c
@@ -407,10 +407,19 @@
 	struct greybus_host_device *hd = urb->context;
 	struct es1_ap_dev *es1 = hd_to_es1(hd);
 	unsigned long flags;
-	/* int status = check_urb_status(urb); */
+	int status = check_urb_status(urb);
+	u8 *data = urb->transfer_buffer + 1;
 	int i;
 
 	/*
+	 * Tell the submitter that the buffer send (attempt) is
+	 * complete, and report the status.  The submitter's buffer
+	 * starts after the one-byte CPort id we inserted.
+	 */
+	data = urb->transfer_buffer + 1;
+	greybus_data_sent(hd, data, status);
+
+	/*
 	 * See if this was an urb in our pool, if so mark it "free", otherwise
 	 * we need to free it ourselves.
 	 */
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c
index c9988fd..74dd48a 100644
--- a/drivers/staging/greybus/operation.c
+++ b/drivers/staging/greybus/operation.c
@@ -230,6 +230,24 @@
 }
 
 /*
+ * Given a pointer to the header in a message sent on a given host
+ * device, return the associated message structure.  (This "header"
+ * is just the buffer pointer we supply to the host device for
+ * sending.)
+ */
+static struct gb_message *
+gb_hd_message_find(struct greybus_host_device *hd, void *header)
+{
+	struct gb_message *message;
+	u8 *result;
+
+	result = (u8 *)header - hd->buffer_headroom - sizeof(*message);
+	message = (struct gb_message *)result;
+
+	return message;
+}
+
+/*
  * Allocate a message to be used for an operation request or
  * response.  For outgoing messages, both types of message contain a
  * common header, which is filled in here.  Incoming requests or
@@ -474,6 +492,32 @@
 }
 
 /*
+ * This function is called when a buffer send request has completed.
+ * The "header" is the message header--the beginning of what we
+ * asked to have sent.
+ *
+ * XXX Mismatch between errno here and operation result code
+ */
+void
+greybus_data_sent(struct greybus_host_device *hd, void *header, int status)
+{
+	struct gb_message *message;
+	struct gb_operation *operation;
+
+	/* If there's no error, there's really nothing to do */
+	if (!status)
+		return;	/* Mark it complete? */
+
+	/* XXX Right now we assume we're an outgoing request */
+	message = gb_hd_message_find(hd, header);
+	operation = message->operation;
+	gb_connection_err(operation->connection, "send error %d\n", status);
+	operation->result = status;	/* XXX */
+	gb_operation_complete(operation);
+}
+EXPORT_SYMBOL_GPL(greybus_data_sent);
+
+/*
  * We've received data on a connection, and it doesn't look like a
  * response, so we assume it's a request.
  *
diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h
index 2fdb41c..3e5e1f5 100644
--- a/drivers/staging/greybus/operation.h
+++ b/drivers/staging/greybus/operation.h
@@ -103,6 +103,9 @@
 
 int gb_operation_status_map(u8 status);
 
+void greybus_data_sent(struct greybus_host_device *hd,
+				void *header, int status);
+
 int gb_operation_init(void);
 void gb_operation_exit(void);