Commit e561f8e2 authored by Michael Tretter's avatar Michael Tretter Committed by Mauro Carvalho Chehab

media: allegro: rework read/write to mailbox

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: default avatarMichael Tretter <m.tretter@pengutronix.de>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 94dc7656
......@@ -612,49 +612,34 @@ 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);
......@@ -662,40 +647,32 @@ static int allegro_mbox_write(struct allegro_dev *dev,
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
......@@ -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;
}
......@@ -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;
......@@ -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;
......@@ -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,
......@@ -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,
......
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