mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-04 10:12:16 +09:00
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 <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
5259ef138c
commit
06a4a061f1
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user