From: Alex Elder Date: Tue, 18 Nov 2014 19:26:40 +0000 (-0600) Subject: greybus: improve data buffer alignment X-Git-Tag: v4.9-rc1~119^2~378^2~21^2~1870^2~14 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=06a4a061f1917ab6dfdddfbf4a13c0a87f207602;p=linux.git 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: Alex Elder Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 062fb1a818ba..a98a2cb67211 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -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; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 301bd4598c11..fa8065156192 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -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 */