Commit 06a4a061 authored by Alex Elder's avatar Alex Elder Committed by Greg Kroah-Hartman

greybus: improve data buffer alignment

For ES1 we need to insert the destination CPort id in whatever we
supply for sending over UniPro.  Currently we allocate one extra
byte supply the caller with an address that's offset by one from
the beginning of the allocated space.

As a result we always return a poorly-aligned buffer pointer.

Instead, allocate enough space so that we can return a better
aligned buffer to the caller.

Notes:
    - It may be that it's more important to supply an aligned
      address to the hardware.
    - We probably need to be more careful about writing into
      these buffers at unaligned offsets anyway.  (E.g., writing
      a 2-byte value at an odd offset can't be assumed to work.)
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 5259ef13
......@@ -20,7 +20,6 @@
#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K)
#define ES1_GBUF_MSG_SIZE PAGE_SIZE
static const struct usb_device_id id_table[] = {
/* Made up numbers for the SVC USB Bridge in ES1 */
{ USB_DEVICE(0xffff, 0x0001) },
......@@ -109,17 +108,19 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size,
/*
* For ES1 we need to insert a byte at the front of the data
* to indicate the destination CPort id. So we allocate one
* extra byte to allow for that.
* to indicate the destination CPort id. We only need one
* extra byte, but we allocate four extra bytes to allow the
* buffer returned to be aligned on a four-byte boundary.
*
* This is only needed for outbound data, but we handle
* buffers for inbound data the same way for consistency.
*
* XXX Do we need to indicate the destination device id too?
*/
buffer = kzalloc(1 + size, gfp_mask);
buffer = kzalloc(GB_BUFFER_ALIGN + size, gfp_mask);
if (!buffer)
return -ENOMEM;
buffer += GB_BUFFER_ALIGN;
/* Insert the cport id for outbound buffers */
if (dest_cport_id != CPORT_ID_BAD && dest_cport_id > (u16)U8_MAX) {
......@@ -128,7 +129,7 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size,
kfree(buffer);
return -EINVAL;
}
*buffer++ = gbuf->dest_cport_id;
*(buffer - 1) = gbuf->dest_cport_id;
gbuf->transfer_buffer = buffer;
gbuf->transfer_buffer_length = size;
......@@ -145,8 +146,8 @@ static void free_gbuf_data(struct gbuf *gbuf)
if (!transfer_buffer)
return;
/* Account for the prepended cport id */
transfer_buffer--;
/* Account for the space set aside for the prepended cport id */
transfer_buffer -= GB_BUFFER_ALIGN;
kfree(transfer_buffer);
gbuf->transfer_buffer = NULL;
}
......
......@@ -70,6 +70,9 @@ struct greybus_host_device;
struct svc_msg;
struct gbuf;
/* Buffers allocated from the host driver will be aligned to this multiple */
#define GB_BUFFER_ALIGN sizeof(u32)
/* Greybus "Host driver" structure, needed by a host controller driver to be
* able to handle both SVC control as well as "real" greybus messages
*/
......
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