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>
This commit is contained in:
Johan Hovold 2015-04-07 11:27:16 +02:00 committed by Greg Kroah-Hartman
parent ac67acd304
commit 7cf7bca9ec
6 changed files with 56 additions and 94 deletions

View File

@ -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
* 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;

View File

@ -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
* 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 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
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 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
}
/*
* 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 void buffer_cancel(void *cookie)
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_in_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);
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);
}

View File

@ -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
* 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 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
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 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id,
}
/*
* 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 void buffer_cancel(void *cookie)
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_in_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);
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);
}

View File

@ -85,9 +85,9 @@ struct svc_msg;
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);
};

View File

@ -140,16 +140,14 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id)
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 @@ static int gb_message_send(struct gb_message *message)
}
/*
* 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 @@ static void gb_message_cancel(struct gb_message *message)
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 @@ static void gb_operation_work(struct work_struct *work)
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 @@ int gb_operation_response_send(struct gb_operation *operation, int errno)
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 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status)
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

View File

@ -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 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,