diff options
author | Alex Elder | 2014-11-20 23:09:13 +0100 |
---|---|---|
committer | Greg Kroah-Hartman | 2014-11-21 21:23:34 +0100 |
commit | 8b337308e7ff71cd6ae6d9c04260f8ada6e98c9e (patch) | |
tree | 947fb6966f46b3e3f8fa5aa3966e0c0695f81f3e /drivers/staging/greybus/operation.c | |
parent | greybus: complete overflow responses (diff) | |
download | kernel-qcow2-linux-8b337308e7ff71cd6ae6d9c04260f8ada6e98c9e.tar.gz kernel-qcow2-linux-8b337308e7ff71cd6ae6d9c04260f8ada6e98c9e.tar.xz kernel-qcow2-linux-8b337308e7ff71cd6ae6d9c04260f8ada6e98c9e.zip |
greybus: have greybus allocate its own buffers
Rather than having the host driver allocate the buffers that the
Greybus core uses to hold its data for sending or receiving, have
the host driver define what it requires those buffers to look like.
Two constraints define what the host driver requires: the maximum
number of bytes that the host device can send in a single request;
and a statement of the "headroom" that needs to be present for
use by the host device.
The direct description of the headroom is that it's the extra byte
the host device needs at the beginning of the "data" portion of
the buffer so the ES1 driver can insert the destination CPort id.
But more generally, the host driver could put other data in there
as well.
By stating these two parameters, Greybus can allocate the buffers it
uses by itself. The host driver still allocates the buffers it uses
for receiving data--the content of those are copied as needed into
Greybus buffers when data arrives.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
Diffstat (limited to 'drivers/staging/greybus/operation.c')
-rw-r--r-- | drivers/staging/greybus/operation.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d91cd5b4b65a..6c66c264891e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -229,6 +229,27 @@ static void operation_timeout(struct work_struct *work) gb_operation_complete(operation); } +static void * +gb_buffer_alloc(struct greybus_host_device *hd, size_t size, gfp_t gfp_flags) +{ + u8 *buffer; + + buffer = kzalloc(hd->buffer_headroom + size, gfp_flags); + if (buffer) + buffer += hd->buffer_headroom; + + return buffer; +} + +static void +gb_buffer_free(struct greybus_host_device *hd, void *buffer) +{ + u8 *allocated = buffer; + + if (allocated) + kfree(allocated - hd->buffer_headroom); +} + /* * Allocate a buffer to be used for an operation request or response * message. For outgoing messages, both types of message contain a @@ -246,9 +267,9 @@ static int gb_operation_message_init(struct gb_operation *operation, struct gb_message *message; struct gb_operation_msg_hdr *header; - if (size > GB_OPERATION_MESSAGE_SIZE_MAX) - return -E2BIG; size += sizeof(*header); + if (size > hd->buffer_size_max) + return -E2BIG; if (request) { message = &operation->request; @@ -257,7 +278,7 @@ static int gb_operation_message_init(struct gb_operation *operation, type |= GB_OPERATION_TYPE_RESPONSE; } - message->buffer = hd->driver->buffer_alloc(size, gfp_flags); + message->buffer = gb_buffer_alloc(hd, size, gfp_flags); if (!message->buffer) return -ENOMEM; message->buffer_size = size; @@ -279,7 +300,7 @@ static void gb_operation_message_exit(struct gb_message *message) struct greybus_host_device *hd; hd = message->operation->connection->hd; - hd->driver->buffer_free(message->buffer); + gb_buffer_free(hd, message->buffer); message->operation = NULL; message->payload = NULL; |