From d98b52b04e5bd3d8c47ca9a9bffcf08a43c944c3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 16:09:17 -0600 Subject: [PATCH] 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 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/es1-ap-usb.c | 11 ++++++- drivers/staging/greybus/operation.c | 44 ++++++++++++++++++++++++++++ drivers/staging/greybus/operation.h | 3 ++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 88436436fcb2..f32c981d184c 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -407,9 +407,18 @@ static void cport_out_callback(struct urb *urb) 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 c9988fd790e3..74dd48a5a489 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -229,6 +229,24 @@ static void operation_timeout(struct work_struct *work) gb_operation_complete(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; +} + /* * Allocate a message to be used for an operation request or * response. For outgoing messages, both types of message contain a @@ -473,6 +491,32 @@ int gb_operation_response_send(struct gb_operation *operation) return 0; } +/* + * 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 2fdb41c154a8..3e5e1f570f3e 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -103,6 +103,9 @@ int gb_operation_wait(struct gb_operation *operation); 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);