Skip to content

Commit

Permalink
media: allegro: rework read/write to mailbox
Browse files Browse the repository at this point in the history
Rework the functions that read and write the SRAM that is used to
communicate with the MCU.

As the functions will not operate on structs but on prepared binary
buffers, make the buffer stride more explicit. Also, avoid any uses of
struct mcu_msg_header to analyze messages in memory, because the header
will be made independent of the binary representation in the mailbox.
Instead explicitly access the mail size field in the mailbox.

As at it, further reduce the dependency between the mailboxes and struct
allegro_dev.

Signed-off-by: Michael Tretter <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
tretter authored and mchehab committed Jul 19, 2020
1 parent 94dc765 commit e561f8e
Showing 1 changed file with 36 additions and 74 deletions.
110 changes: 36 additions & 74 deletions drivers/staging/media/allegro-dvt/allegro-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,90 +612,67 @@ static struct allegro_mbox *allegro_mbox_init(struct allegro_dev *dev,
return mbox;
}

static int allegro_mbox_write(struct allegro_dev *dev,
struct allegro_mbox *mbox, void *src, size_t size)
static int allegro_mbox_write(struct allegro_mbox *mbox,
const u32 *src, size_t size)
{
struct mcu_msg_header *header = src;
struct regmap *sram = mbox->dev->sram;
unsigned int tail;
size_t size_no_wrap;
int err = 0;
int stride = regmap_get_reg_stride(sram);

if (!src)
return -EINVAL;

if (size > mbox->size) {
v4l2_err(&dev->v4l2_dev,
"message (%zu bytes) too large for mailbox (%zu bytes)\n",
size, mbox->size);
return -EINVAL;
}

if (header->length != size - sizeof(*header)) {
v4l2_err(&dev->v4l2_dev,
"invalid message length: %u bytes (expected %zu bytes)\n",
header->length, size - sizeof(*header));
if (size > mbox->size)
return -EINVAL;
}

v4l2_dbg(2, debug, &dev->v4l2_dev,
"write command message: type %s, body length %d\n",
msg_type_name(header->type), header->length);

mutex_lock(&mbox->lock);
regmap_read(dev->sram, mbox->tail, &tail);
regmap_read(sram, mbox->tail, &tail);
if (tail > mbox->size) {
v4l2_err(&dev->v4l2_dev,
"invalid tail (0x%x): must be smaller than mailbox size (0x%zx)\n",
tail, mbox->size);
err = -EIO;
goto out;
}
size_no_wrap = min(size, mbox->size - (size_t)tail);
regmap_bulk_write(dev->sram, mbox->data + tail, src, size_no_wrap / 4);
regmap_bulk_write(dev->sram, mbox->data,
src + size_no_wrap, (size - size_no_wrap) / 4);
regmap_write(dev->sram, mbox->tail, (tail + size) % mbox->size);
regmap_bulk_write(sram, mbox->data + tail,
src, size_no_wrap / stride);
regmap_bulk_write(sram, mbox->data,
src + (size_no_wrap / sizeof(*src)),
(size - size_no_wrap) / stride);
regmap_write(sram, mbox->tail, (tail + size) % mbox->size);

out:
mutex_unlock(&mbox->lock);

return err;
}

static ssize_t allegro_mbox_read(struct allegro_dev *dev,
struct allegro_mbox *mbox,
void *dst, size_t nbyte)
static ssize_t allegro_mbox_read(struct allegro_mbox *mbox,
u32 *dst, size_t nbyte)
{
struct mcu_msg_header *header;
struct {
u16 length;
u16 type;
} __attribute__ ((__packed__)) *header;
struct regmap *sram = mbox->dev->sram;
unsigned int head;
ssize_t size;
size_t body_no_wrap;
int stride = regmap_get_reg_stride(sram);

regmap_read(dev->sram, mbox->head, &head);
if (head > mbox->size) {
v4l2_err(&dev->v4l2_dev,
"invalid head (0x%x): must be smaller than mailbox size (0x%zx)\n",
head, mbox->size);
regmap_read(sram, mbox->head, &head);
if (head > mbox->size)
return -EIO;
}

/* Assume that the header does not wrap. */
regmap_bulk_read(dev->sram, mbox->data + head,
dst, sizeof(*header) / 4);
header = dst;
regmap_bulk_read(sram, mbox->data + head,
dst, sizeof(*header) / stride);
header = (void *)dst;
size = header->length + sizeof(*header);
if (size > mbox->size || size & 0x3) {
v4l2_err(&dev->v4l2_dev,
"invalid message length: %zu bytes (maximum %zu bytes)\n",
header->length + sizeof(*header), mbox->size);
if (size > mbox->size || size & 0x3)
return -EIO;
}
if (size > nbyte) {
v4l2_err(&dev->v4l2_dev,
"destination buffer too small: %zu bytes (need %zu bytes)\n",
nbyte, size);
if (size > nbyte)
return -EINVAL;
}

/*
* The message might wrap within the mailbox. If the message does not
Expand All @@ -708,17 +685,14 @@ static ssize_t allegro_mbox_read(struct allegro_dev *dev,
*/
body_no_wrap = min((size_t)header->length,
(size_t)(mbox->size - (head + sizeof(*header))));
regmap_bulk_read(dev->sram, mbox->data + head + sizeof(*header),
dst + sizeof(*header), body_no_wrap / 4);
regmap_bulk_read(dev->sram, mbox->data,
dst + sizeof(*header) + body_no_wrap,
(header->length - body_no_wrap) / 4);
regmap_bulk_read(sram, mbox->data + head + sizeof(*header),
dst + (sizeof(*header) / sizeof(*dst)),
body_no_wrap / stride);
regmap_bulk_read(sram, mbox->data,
dst + (sizeof(*header) + body_no_wrap) / sizeof(*dst),
(header->length - body_no_wrap) / stride);

regmap_write(dev->sram, mbox->head, (head + size) % mbox->size);

v4l2_dbg(2, debug, &dev->v4l2_dev,
"read status message: type %s, body length %d\n",
msg_type_name(header->type), header->length);
regmap_write(sram, mbox->head, (head + size) % mbox->size);

return size;
}
Expand All @@ -735,7 +709,7 @@ static int allegro_mbox_send(struct allegro_mbox *mbox, void *msg)
ssize_t size = sizeof(*header) + header->length;
int err;

err = allegro_mbox_write(dev, mbox, msg, size);
err = allegro_mbox_write(mbox, msg, size);
if (err)
goto out;

Expand All @@ -759,7 +733,7 @@ static void allegro_mbox_notify(struct allegro_mbox *mbox)
if (!msg)
return;

size = allegro_mbox_read(dev, mbox, msg, sizeof(*msg));
size = allegro_mbox_read(mbox, (u32 *)msg, sizeof(*msg));
if (size < 0)
goto out;

Expand Down Expand Up @@ -1604,12 +1578,6 @@ allegro_handle_create_channel(struct allegro_dev *dev,
struct allegro_channel *channel;
int err = 0;

if (msg->header.length != sizeof(*msg) - sizeof(msg->header))
v4l2_warn(&dev->v4l2_dev,
"received message has %d bytes, but expected %zu\n",
msg->header.length,
sizeof(*msg) - sizeof(msg->header));

channel = allegro_find_channel_by_user_id(dev, msg->user_id);
if (IS_ERR(channel)) {
v4l2_warn(&dev->v4l2_dev,
Expand Down Expand Up @@ -1703,12 +1671,6 @@ allegro_handle_encode_frame(struct allegro_dev *dev,
{
struct allegro_channel *channel;

if (msg->header.length != sizeof(*msg) - sizeof(msg->header))
v4l2_warn(&dev->v4l2_dev,
"received message has %d bytes, but expected %zu\n",
msg->header.length,
sizeof(*msg) - sizeof(msg->header));

channel = allegro_find_channel_by_channel_id(dev, msg->channel_id);
if (IS_ERR(channel)) {
v4l2_err(&dev->v4l2_dev,
Expand Down

0 comments on commit e561f8e

Please sign in to comment.