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);