]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
greybus: improve data buffer alignment
authorAlex Elder <elder@linaro.org>
Tue, 18 Nov 2014 19:26:40 +0000 (13:26 -0600)
committerGreg Kroah-Hartman <greg@kroah.com>
Tue, 18 Nov 2014 20:46:15 +0000 (12:46 -0800)
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 <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
drivers/staging/greybus/es1-ap-usb.c
drivers/staging/greybus/greybus.h

index 062fb1a818baadeae0116221a11b730a22226ad3..a98a2cb67211862d67e56241f01a1ed069dbdb2e 100644 (file)
@@ -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;
 }
index 301bd4598c117241fde4a36601e9bd3e1e8226bb..fa8065156192245824030b14cb9ed7fdf649fc8b 100644 (file)
@@ -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
  */