greybus: pass messages to host drivers

Pass structured greybus messages rather than buffers to the host
drivers.

This will allow us to separate the transfer buffers from the message
structures.

Rename the related functions to reflect the new interface.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c
index 0ac2fb8..da62c54 100644
--- a/drivers/staging/greybus/core.c
+++ b/drivers/staging/greybus/core.c
@@ -173,7 +173,7 @@
 	 * Validate that the driver implements all of the callbacks
 	 * so that we don't have to every time we make them.
 	 */
-	if ((!driver->buffer_send) || (!driver->buffer_cancel) ||
+	if ((!driver->message_send) || (!driver->message_cancel) ||
 	    (!driver->submit_svc)) {
 		pr_err("Must implement all greybus_host_driver callbacks!\n");
 		return NULL;
diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c
index b9fd511..55f8c75 100644
--- a/drivers/staging/greybus/es1.c
+++ b/drivers/staging/greybus/es1.c
@@ -214,26 +214,21 @@
  * error otherwise.  If the caller wishes to cancel the in-flight
  * buffer, it must supply the returned cookie to the cancel routine.
  */
-static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
-			void *buffer, size_t buffer_size, gfp_t gfp_mask)
+static void *message_send(struct greybus_host_device *hd, u16 cport_id,
+			struct gb_message *message, gfp_t gfp_mask)
 {
 	struct es1_ap_dev *es1 = hd_to_es1(hd);
 	struct usb_device *udev = es1->usb_dev;
-	u8 *transfer_buffer = buffer;
+	u8 *transfer_buffer;
+	size_t buffer_size;
 	int transfer_buffer_size;
 	int retval;
 	struct urb *urb;
 
-	if (!buffer) {
-		pr_err("null buffer supplied to send\n");
-		return ERR_PTR(-EINVAL);
-	}
-	if (buffer_size > (size_t)INT_MAX) {
-		pr_err("bad buffer size (%zu) supplied to send\n", buffer_size);
-		return ERR_PTR(-EINVAL);
-	}
-	transfer_buffer--;
-	transfer_buffer_size = buffer_size + 1;
+	buffer_size = hd->buffer_headroom + sizeof(*message->header) +
+							message->payload_size;
+	transfer_buffer = message->buffer + hd->buffer_headroom - 1;
+	transfer_buffer_size = buffer_size - (hd->buffer_headroom - 1);
 
 	/*
 	 * The data actually transferred will include an indication
@@ -259,7 +254,7 @@
 	usb_fill_bulk_urb(urb, udev,
 			  usb_sndbulkpipe(udev, es1->cport_out_endpoint),
 			  transfer_buffer, transfer_buffer_size,
-			  cport_out_callback, hd);
+			  cport_out_callback, message);
 	retval = usb_submit_urb(urb, gfp_mask);
 	if (retval) {
 		pr_err("error %d submitting URB\n", retval);
@@ -271,17 +266,17 @@
 }
 
 /*
- * The cookie value supplied is the value that buffer_send()
- * returned to its caller.  It identifies the buffer that should be
+ * The cookie value supplied is the value that message_send()
+ * returned to its caller.  It identifies the message that should be
  * canceled.  This function must also handle (which is to say,
  * ignore) a null cookie value.
  */
-static void buffer_cancel(void *cookie)
+static void message_cancel(void *cookie)
 {
 
 	/*
 	 * We really should be defensive and track all outstanding
-	 * (sent) buffers rather than trusting the cookie provided
+	 * (sent) messages rather than trusting the cookie provided
 	 * is valid.  For the time being, this will do.
 	 */
 	if (cookie)
@@ -290,8 +285,8 @@
 
 static struct greybus_host_driver es1_driver = {
 	.hd_priv_size		= sizeof(struct es1_ap_dev),
-	.buffer_send		= buffer_send,
-	.buffer_cancel		= buffer_cancel,
+	.message_send		= message_send,
+	.message_cancel		= message_cancel,
 	.submit_svc		= submit_svc,
 };
 
@@ -439,18 +434,17 @@
 
 static void cport_out_callback(struct urb *urb)
 {
-	struct greybus_host_device *hd = urb->context;
+	struct gb_message *message = urb->context;
+	struct greybus_host_device *hd = message->operation->connection->hd;
 	struct es1_ap_dev *es1 = hd_to_es1(hd);
 	int status = check_urb_status(urb);
-	u8 *data = urb->transfer_buffer + 1;
 
 	/*
-	 * 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.
+	 * Tell the submitter that the message send (attempt) is
+	 * complete, and report the status.
 	 */
-	data = urb->transfer_buffer + 1;
-	greybus_data_sent(hd, data, status);
+	greybus_message_sent(hd, message, status);
+
 	free_urb(es1, urb);
 }
 
diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c
index 526e23c..10b21df 100644
--- a/drivers/staging/greybus/es2.c
+++ b/drivers/staging/greybus/es2.c
@@ -214,26 +214,21 @@
  * error otherwise.  If the caller wishes to cancel the in-flight
  * buffer, it must supply the returned cookie to the cancel routine.
  */
-static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
-			void *buffer, size_t buffer_size, gfp_t gfp_mask)
+static void *message_send(struct greybus_host_device *hd, u16 cport_id,
+			struct gb_message *message, gfp_t gfp_mask)
 {
 	struct es1_ap_dev *es1 = hd_to_es1(hd);
 	struct usb_device *udev = es1->usb_dev;
-	u8 *transfer_buffer = buffer;
+	u8 *transfer_buffer;
+	size_t buffer_size;
 	int transfer_buffer_size;
 	int retval;
 	struct urb *urb;
 
-	if (!buffer) {
-		pr_err("null buffer supplied to send\n");
-		return ERR_PTR(-EINVAL);
-	}
-	if (buffer_size > (size_t)INT_MAX) {
-		pr_err("bad buffer size (%zu) supplied to send\n", buffer_size);
-		return ERR_PTR(-EINVAL);
-	}
-	transfer_buffer--;
-	transfer_buffer_size = buffer_size + 1;
+	buffer_size = hd->buffer_headroom + sizeof(*message->header) +
+							message->payload_size;
+	transfer_buffer = message->buffer + hd->buffer_headroom - 1;
+	transfer_buffer_size = buffer_size - (hd->buffer_headroom - 1);
 
 	/*
 	 * The data actually transferred will include an indication
@@ -259,7 +254,7 @@
 	usb_fill_bulk_urb(urb, udev,
 			  usb_sndbulkpipe(udev, es1->cport_out_endpoint),
 			  transfer_buffer, transfer_buffer_size,
-			  cport_out_callback, hd);
+			  cport_out_callback, message);
 	retval = usb_submit_urb(urb, gfp_mask);
 	if (retval) {
 		pr_err("error %d submitting URB\n", retval);
@@ -271,17 +266,17 @@
 }
 
 /*
- * The cookie value supplied is the value that buffer_send()
- * returned to its caller.  It identifies the buffer that should be
+ * The cookie value supplied is the value that message_send()
+ * returned to its caller.  It identifies the message that should be
  * canceled.  This function must also handle (which is to say,
  * ignore) a null cookie value.
  */
-static void buffer_cancel(void *cookie)
+static void message_cancel(void *cookie)
 {
 
 	/*
 	 * We really should be defensive and track all outstanding
-	 * (sent) buffers rather than trusting the cookie provided
+	 * (sent) messages rather than trusting the cookie provided
 	 * is valid.  For the time being, this will do.
 	 */
 	if (cookie)
@@ -290,8 +285,8 @@
 
 static struct greybus_host_driver es1_driver = {
 	.hd_priv_size		= sizeof(struct es1_ap_dev),
-	.buffer_send		= buffer_send,
-	.buffer_cancel		= buffer_cancel,
+	.message_send		= message_send,
+	.message_cancel		= message_cancel,
 	.submit_svc		= submit_svc,
 };
 
@@ -439,18 +434,17 @@
 
 static void cport_out_callback(struct urb *urb)
 {
-	struct greybus_host_device *hd = urb->context;
+	struct gb_message *message = urb->context;
+	struct greybus_host_device *hd = message->operation->connection->hd;
 	struct es1_ap_dev *es1 = hd_to_es1(hd);
 	int status = check_urb_status(urb);
-	u8 *data = urb->transfer_buffer + 1;
 
 	/*
-	 * 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.
+	 * Tell the submitter that the message send (attempt) is
+	 * complete, and report the status.
 	 */
-	data = urb->transfer_buffer + 1;
-	greybus_data_sent(hd, data, status);
+	greybus_message_sent(hd, message, status);
+
 	free_urb(es1, urb);
 }
 
diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h
index fb90f96..6f156e5 100644
--- a/drivers/staging/greybus/greybus.h
+++ b/drivers/staging/greybus/greybus.h
@@ -85,9 +85,9 @@
 struct greybus_host_driver {
 	size_t	hd_priv_size;
 
-	void *(*buffer_send)(struct greybus_host_device *hd, u16 dest_cport_id,
-			void *buffer, size_t buffer_size, gfp_t gfp_mask);
-	void (*buffer_cancel)(void *cookie);
+	void *(*message_send)(struct greybus_host_device *hd, u16 dest_cport_id,
+			struct gb_message *message, gfp_t gfp_mask);
+	void (*message_cancel)(void *cookie);
 	int (*submit_svc)(struct svc_msg *svc_msg,
 			    struct greybus_host_device *hd);
 };
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c
index 2dbb1e9..cdfb893 100644
--- a/drivers/staging/greybus/operation.c
+++ b/drivers/staging/greybus/operation.c
@@ -140,16 +140,14 @@
 
 static int gb_message_send(struct gb_message *message)
 {
-	size_t message_size = sizeof(*message->header) + message->payload_size;
 	struct gb_connection *connection = message->operation->connection;
 	int ret = 0;
 	void *cookie;
 
 	mutex_lock(&gb_message_mutex);
-	cookie = connection->hd->driver->buffer_send(connection->hd,
+	cookie = connection->hd->driver->message_send(connection->hd,
 					connection->hd_cport_id,
-					message->header,
-					message_size,
+					message,
 					GFP_KERNEL);
 	if (IS_ERR(cookie))
 		ret = PTR_ERR(cookie);
@@ -161,8 +159,7 @@
 }
 
 /*
- * Cancel a message whose buffer we have passed to the host device
- * layer to be sent.
+ * Cancel a message we have passed to the host device layer to be sent.
  */
 static void gb_message_cancel(struct gb_message *message)
 {
@@ -171,7 +168,7 @@
 		struct greybus_host_device *hd;
 
 		hd = message->operation->connection->hd;
-		hd->driver->buffer_cancel(message->cookie);
+		hd->driver->message_cancel(message->cookie);
 	}
 	mutex_unlock(&gb_message_mutex);
 }
@@ -225,25 +222,6 @@
 	gb_operation_put(operation);
 }
 
-
-/*
- * 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;
-}
-
 static void gb_operation_message_init(struct greybus_host_device *hd,
 				struct gb_message *message, u16 operation_id,
 				size_t payload_size, u8 type)
@@ -737,18 +715,14 @@
 EXPORT_SYMBOL_GPL(gb_operation_response_send);
 
 /*
- * 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.
+ * This function is called when a message send request has completed.
  */
-void
-greybus_data_sent(struct greybus_host_device *hd, void *header, int status)
+void greybus_message_sent(struct greybus_host_device *hd,
+					struct gb_message *message, int status)
 {
-	struct gb_message *message;
 	struct gb_operation *operation;
 
 	/* Get the message and record that it is no longer in flight */
-	message = gb_hd_message_find(hd, header);
 	message->cookie = NULL;
 
 	/*
@@ -773,7 +747,7 @@
 			queue_work(gb_operation_workqueue, &operation->work);
 	}
 }
-EXPORT_SYMBOL_GPL(greybus_data_sent);
+EXPORT_SYMBOL_GPL(greybus_message_sent);
 
 /*
  * We've received data on a connection, and it doesn't look like a
diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h
index 5ed1f6e..cbd347c 100644
--- a/drivers/staging/greybus/operation.h
+++ b/drivers/staging/greybus/operation.h
@@ -147,8 +147,8 @@
 
 void gb_operation_cancel(struct gb_operation *operation, int errno);
 
-void greybus_data_sent(struct greybus_host_device *hd,
-				void *header, int status);
+void greybus_message_sent(struct greybus_host_device *hd,
+				struct gb_message *message, int status);
 
 int gb_operation_sync(struct gb_connection *connection, int type,
 		      void *request, int request_size,