Commit 7cf7bca9 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

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: default avatarJohan Hovold <johan@hovoldconsulting.com>
Reviewed-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent ac67acd3
...@@ -173,7 +173,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ...@@ -173,7 +173,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
* Validate that the driver implements all of the callbacks * Validate that the driver implements all of the callbacks
* so that we don't have to every time we make them. * 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)) { (!driver->submit_svc)) {
pr_err("Must implement all greybus_host_driver callbacks!\n"); pr_err("Must implement all greybus_host_driver callbacks!\n");
return NULL; return NULL;
......
...@@ -214,26 +214,21 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) ...@@ -214,26 +214,21 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb)
* error otherwise. If the caller wishes to cancel the in-flight * error otherwise. If the caller wishes to cancel the in-flight
* buffer, it must supply the returned cookie to the cancel routine. * buffer, it must supply the returned cookie to the cancel routine.
*/ */
static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, static void *message_send(struct greybus_host_device *hd, u16 cport_id,
void *buffer, size_t buffer_size, gfp_t gfp_mask) struct gb_message *message, gfp_t gfp_mask)
{ {
struct es1_ap_dev *es1 = hd_to_es1(hd); struct es1_ap_dev *es1 = hd_to_es1(hd);
struct usb_device *udev = es1->usb_dev; struct usb_device *udev = es1->usb_dev;
u8 *transfer_buffer = buffer; u8 *transfer_buffer;
size_t buffer_size;
int transfer_buffer_size; int transfer_buffer_size;
int retval; int retval;
struct urb *urb; struct urb *urb;
if (!buffer) { buffer_size = hd->buffer_headroom + sizeof(*message->header) +
pr_err("null buffer supplied to send\n"); message->payload_size;
return ERR_PTR(-EINVAL); transfer_buffer = message->buffer + hd->buffer_headroom - 1;
} transfer_buffer_size = buffer_size - (hd->buffer_headroom - 1);
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;
/* /*
* The data actually transferred will include an indication * The data actually transferred will include an indication
...@@ -259,7 +254,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, ...@@ -259,7 +254,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
usb_fill_bulk_urb(urb, udev, usb_fill_bulk_urb(urb, udev,
usb_sndbulkpipe(udev, es1->cport_out_endpoint), usb_sndbulkpipe(udev, es1->cport_out_endpoint),
transfer_buffer, transfer_buffer_size, transfer_buffer, transfer_buffer_size,
cport_out_callback, hd); cport_out_callback, message);
retval = usb_submit_urb(urb, gfp_mask); retval = usb_submit_urb(urb, gfp_mask);
if (retval) { if (retval) {
pr_err("error %d submitting URB\n", retval); pr_err("error %d submitting URB\n", retval);
...@@ -271,17 +266,17 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, ...@@ -271,17 +266,17 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
} }
/* /*
* The cookie value supplied is the value that buffer_send() * The cookie value supplied is the value that message_send()
* returned to its caller. It identifies the buffer that should be * returned to its caller. It identifies the message that should be
* canceled. This function must also handle (which is to say, * canceled. This function must also handle (which is to say,
* ignore) a null cookie value. * 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 * 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. * is valid. For the time being, this will do.
*/ */
if (cookie) if (cookie)
...@@ -290,8 +285,8 @@ static void buffer_cancel(void *cookie) ...@@ -290,8 +285,8 @@ static void buffer_cancel(void *cookie)
static struct greybus_host_driver es1_driver = { static struct greybus_host_driver es1_driver = {
.hd_priv_size = sizeof(struct es1_ap_dev), .hd_priv_size = sizeof(struct es1_ap_dev),
.buffer_send = buffer_send, .message_send = message_send,
.buffer_cancel = buffer_cancel, .message_cancel = message_cancel,
.submit_svc = submit_svc, .submit_svc = submit_svc,
}; };
...@@ -439,18 +434,17 @@ static void cport_in_callback(struct urb *urb) ...@@ -439,18 +434,17 @@ static void cport_in_callback(struct urb *urb)
static void cport_out_callback(struct urb *urb) 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); struct es1_ap_dev *es1 = hd_to_es1(hd);
int status = check_urb_status(urb); int status = check_urb_status(urb);
u8 *data = urb->transfer_buffer + 1;
/* /*
* Tell the submitter that the buffer send (attempt) is * Tell the submitter that the message send (attempt) is
* complete, and report the status. The submitter's buffer * complete, and report the status.
* starts after the one-byte CPort id we inserted.
*/ */
data = urb->transfer_buffer + 1; greybus_message_sent(hd, message, status);
greybus_data_sent(hd, data, status);
free_urb(es1, urb); free_urb(es1, urb);
} }
......
...@@ -214,26 +214,21 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) ...@@ -214,26 +214,21 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb)
* error otherwise. If the caller wishes to cancel the in-flight * error otherwise. If the caller wishes to cancel the in-flight
* buffer, it must supply the returned cookie to the cancel routine. * buffer, it must supply the returned cookie to the cancel routine.
*/ */
static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, static void *message_send(struct greybus_host_device *hd, u16 cport_id,
void *buffer, size_t buffer_size, gfp_t gfp_mask) struct gb_message *message, gfp_t gfp_mask)
{ {
struct es1_ap_dev *es1 = hd_to_es1(hd); struct es1_ap_dev *es1 = hd_to_es1(hd);
struct usb_device *udev = es1->usb_dev; struct usb_device *udev = es1->usb_dev;
u8 *transfer_buffer = buffer; u8 *transfer_buffer;
size_t buffer_size;
int transfer_buffer_size; int transfer_buffer_size;
int retval; int retval;
struct urb *urb; struct urb *urb;
if (!buffer) { buffer_size = hd->buffer_headroom + sizeof(*message->header) +
pr_err("null buffer supplied to send\n"); message->payload_size;
return ERR_PTR(-EINVAL); transfer_buffer = message->buffer + hd->buffer_headroom - 1;
} transfer_buffer_size = buffer_size - (hd->buffer_headroom - 1);
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;
/* /*
* The data actually transferred will include an indication * The data actually transferred will include an indication
...@@ -259,7 +254,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, ...@@ -259,7 +254,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
usb_fill_bulk_urb(urb, udev, usb_fill_bulk_urb(urb, udev,
usb_sndbulkpipe(udev, es1->cport_out_endpoint), usb_sndbulkpipe(udev, es1->cport_out_endpoint),
transfer_buffer, transfer_buffer_size, transfer_buffer, transfer_buffer_size,
cport_out_callback, hd); cport_out_callback, message);
retval = usb_submit_urb(urb, gfp_mask); retval = usb_submit_urb(urb, gfp_mask);
if (retval) { if (retval) {
pr_err("error %d submitting URB\n", retval); pr_err("error %d submitting URB\n", retval);
...@@ -271,17 +266,17 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, ...@@ -271,17 +266,17 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
} }
/* /*
* The cookie value supplied is the value that buffer_send() * The cookie value supplied is the value that message_send()
* returned to its caller. It identifies the buffer that should be * returned to its caller. It identifies the message that should be
* canceled. This function must also handle (which is to say, * canceled. This function must also handle (which is to say,
* ignore) a null cookie value. * 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 * 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. * is valid. For the time being, this will do.
*/ */
if (cookie) if (cookie)
...@@ -290,8 +285,8 @@ static void buffer_cancel(void *cookie) ...@@ -290,8 +285,8 @@ static void buffer_cancel(void *cookie)
static struct greybus_host_driver es1_driver = { static struct greybus_host_driver es1_driver = {
.hd_priv_size = sizeof(struct es1_ap_dev), .hd_priv_size = sizeof(struct es1_ap_dev),
.buffer_send = buffer_send, .message_send = message_send,
.buffer_cancel = buffer_cancel, .message_cancel = message_cancel,
.submit_svc = submit_svc, .submit_svc = submit_svc,
}; };
...@@ -439,18 +434,17 @@ static void cport_in_callback(struct urb *urb) ...@@ -439,18 +434,17 @@ static void cport_in_callback(struct urb *urb)
static void cport_out_callback(struct urb *urb) 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); struct es1_ap_dev *es1 = hd_to_es1(hd);
int status = check_urb_status(urb); int status = check_urb_status(urb);
u8 *data = urb->transfer_buffer + 1;
/* /*
* Tell the submitter that the buffer send (attempt) is * Tell the submitter that the message send (attempt) is
* complete, and report the status. The submitter's buffer * complete, and report the status.
* starts after the one-byte CPort id we inserted.
*/ */
data = urb->transfer_buffer + 1; greybus_message_sent(hd, message, status);
greybus_data_sent(hd, data, status);
free_urb(es1, urb); free_urb(es1, urb);
} }
......
...@@ -85,9 +85,9 @@ struct svc_msg; ...@@ -85,9 +85,9 @@ struct svc_msg;
struct greybus_host_driver { struct greybus_host_driver {
size_t hd_priv_size; size_t hd_priv_size;
void *(*buffer_send)(struct greybus_host_device *hd, u16 dest_cport_id, void *(*message_send)(struct greybus_host_device *hd, u16 dest_cport_id,
void *buffer, size_t buffer_size, gfp_t gfp_mask); struct gb_message *message, gfp_t gfp_mask);
void (*buffer_cancel)(void *cookie); void (*message_cancel)(void *cookie);
int (*submit_svc)(struct svc_msg *svc_msg, int (*submit_svc)(struct svc_msg *svc_msg,
struct greybus_host_device *hd); struct greybus_host_device *hd);
}; };
......
...@@ -140,16 +140,14 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id) ...@@ -140,16 +140,14 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id)
static int gb_message_send(struct gb_message *message) 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; struct gb_connection *connection = message->operation->connection;
int ret = 0; int ret = 0;
void *cookie; void *cookie;
mutex_lock(&gb_message_mutex); 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, connection->hd_cport_id,
message->header, message,
message_size,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(cookie)) if (IS_ERR(cookie))
ret = PTR_ERR(cookie); ret = PTR_ERR(cookie);
...@@ -161,8 +159,7 @@ static int gb_message_send(struct gb_message *message) ...@@ -161,8 +159,7 @@ static int gb_message_send(struct gb_message *message)
} }
/* /*
* Cancel a message whose buffer we have passed to the host device * Cancel a message we have passed to the host device layer to be sent.
* layer to be sent.
*/ */
static void gb_message_cancel(struct gb_message *message) static void gb_message_cancel(struct gb_message *message)
{ {
...@@ -171,7 +168,7 @@ static void gb_message_cancel(struct gb_message *message) ...@@ -171,7 +168,7 @@ static void gb_message_cancel(struct gb_message *message)
struct greybus_host_device *hd; struct greybus_host_device *hd;
hd = message->operation->connection->hd; hd = message->operation->connection->hd;
hd->driver->buffer_cancel(message->cookie); hd->driver->message_cancel(message->cookie);
} }
mutex_unlock(&gb_message_mutex); mutex_unlock(&gb_message_mutex);
} }
...@@ -225,25 +222,6 @@ static void gb_operation_work(struct work_struct *work) ...@@ -225,25 +222,6 @@ static void gb_operation_work(struct work_struct *work)
gb_operation_put(operation); 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, static void gb_operation_message_init(struct greybus_host_device *hd,
struct gb_message *message, u16 operation_id, struct gb_message *message, u16 operation_id,
size_t payload_size, u8 type) size_t payload_size, u8 type)
...@@ -737,18 +715,14 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) ...@@ -737,18 +715,14 @@ int gb_operation_response_send(struct gb_operation *operation, int errno)
EXPORT_SYMBOL_GPL(gb_operation_response_send); EXPORT_SYMBOL_GPL(gb_operation_response_send);
/* /*
* This function is called when a buffer send request has completed. * This function is called when a message send request has completed.
* The "header" is the message header--the beginning of what we
* asked to have sent.
*/ */
void void greybus_message_sent(struct greybus_host_device *hd,
greybus_data_sent(struct greybus_host_device *hd, void *header, int status) struct gb_message *message, int status)
{ {
struct gb_message *message;
struct gb_operation *operation; struct gb_operation *operation;
/* Get the message and record that it is no longer in flight */ /* Get the message and record that it is no longer in flight */
message = gb_hd_message_find(hd, header);
message->cookie = NULL; message->cookie = NULL;
/* /*
...@@ -773,7 +747,7 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) ...@@ -773,7 +747,7 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status)
queue_work(gb_operation_workqueue, &operation->work); 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 * We've received data on a connection, and it doesn't look like a
......
...@@ -147,8 +147,8 @@ int gb_operation_response_send(struct gb_operation *operation, int errno); ...@@ -147,8 +147,8 @@ int gb_operation_response_send(struct gb_operation *operation, int errno);
void gb_operation_cancel(struct gb_operation *operation, int errno); void gb_operation_cancel(struct gb_operation *operation, int errno);
void greybus_data_sent(struct greybus_host_device *hd, void greybus_message_sent(struct greybus_host_device *hd,
void *header, int status); struct gb_message *message, int status);
int gb_operation_sync(struct gb_connection *connection, int type, int gb_operation_sync(struct gb_connection *connection, int type,
void *request, int request_size, void *request, int request_size,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment