Commit 17aed904 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Mauro Carvalho Chehab

media: staging: tegra-vde: Align bitstream size to 16K

I've noticed that decoding fails sometime if size of bitstream buffer
isn't aligned to 16K, probably because HW fetches data from memory in
a 16K granularity and if the last chunk of data isn't aligned, HW reads
garbage data beyond the dmabuf and tries to parse it.
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarHans Verkuil <hansverk@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent a2b2eff6
...@@ -440,7 +440,7 @@ static int tegra_vde_setup_hw_context(struct tegra_vde *vde, ...@@ -440,7 +440,7 @@ static int tegra_vde_setup_hw_context(struct tegra_vde *vde,
VDE_WR(value, vde->sxe + 0x4C); VDE_WR(value, vde->sxe + 0x4C);
value = 0x03800000; value = 0x03800000;
value |= min_t(size_t, bitstream_data_size, SZ_1M); value |= bitstream_data_size & GENMASK(19, 15);
VDE_WR(value, vde->sxe + 0x68); VDE_WR(value, vde->sxe + 0x68);
...@@ -522,7 +522,8 @@ static void tegra_vde_detach_and_put_dmabuf(struct dma_buf_attachment *a, ...@@ -522,7 +522,8 @@ static void tegra_vde_detach_and_put_dmabuf(struct dma_buf_attachment *a,
static int tegra_vde_attach_dmabuf(struct device *dev, static int tegra_vde_attach_dmabuf(struct device *dev,
int fd, int fd,
unsigned long offset, unsigned long offset,
unsigned int min_size, size_t min_size,
size_t align_size,
struct dma_buf_attachment **a, struct dma_buf_attachment **a,
dma_addr_t *addr, dma_addr_t *addr,
struct sg_table **s, struct sg_table **s,
...@@ -540,9 +541,16 @@ static int tegra_vde_attach_dmabuf(struct device *dev, ...@@ -540,9 +541,16 @@ static int tegra_vde_attach_dmabuf(struct device *dev,
return PTR_ERR(dmabuf); return PTR_ERR(dmabuf);
} }
if (dmabuf->size & (align_size - 1)) {
dev_err(dev, "Unaligned dmabuf 0x%zX, "
"should be aligned to 0x%zX\n",
dmabuf->size, align_size);
return -EINVAL;
}
if ((u64)offset + min_size > dmabuf->size) { if ((u64)offset + min_size > dmabuf->size) {
dev_err(dev, "Too small dmabuf size %zu @0x%lX, " dev_err(dev, "Too small dmabuf size %zu @0x%lX, "
"should be at least %d\n", "should be at least %zu\n",
dmabuf->size, offset, min_size); dmabuf->size, offset, min_size);
return -EINVAL; return -EINVAL;
} }
...@@ -596,7 +604,7 @@ static int tegra_vde_attach_dmabufs_to_frame(struct device *dev, ...@@ -596,7 +604,7 @@ static int tegra_vde_attach_dmabufs_to_frame(struct device *dev,
int err; int err;
err = tegra_vde_attach_dmabuf(dev, src->y_fd, err = tegra_vde_attach_dmabuf(dev, src->y_fd,
src->y_offset, csize * 4, src->y_offset, csize * 4, SZ_256,
&frame->y_dmabuf_attachment, &frame->y_dmabuf_attachment,
&frame->y_addr, &frame->y_addr,
&frame->y_sgt, &frame->y_sgt,
...@@ -605,7 +613,7 @@ static int tegra_vde_attach_dmabufs_to_frame(struct device *dev, ...@@ -605,7 +613,7 @@ static int tegra_vde_attach_dmabufs_to_frame(struct device *dev,
return err; return err;
err = tegra_vde_attach_dmabuf(dev, src->cb_fd, err = tegra_vde_attach_dmabuf(dev, src->cb_fd,
src->cb_offset, csize, src->cb_offset, csize, SZ_256,
&frame->cb_dmabuf_attachment, &frame->cb_dmabuf_attachment,
&frame->cb_addr, &frame->cb_addr,
&frame->cb_sgt, &frame->cb_sgt,
...@@ -614,7 +622,7 @@ static int tegra_vde_attach_dmabufs_to_frame(struct device *dev, ...@@ -614,7 +622,7 @@ static int tegra_vde_attach_dmabufs_to_frame(struct device *dev,
goto err_release_y; goto err_release_y;
err = tegra_vde_attach_dmabuf(dev, src->cr_fd, err = tegra_vde_attach_dmabuf(dev, src->cr_fd,
src->cr_offset, csize, src->cr_offset, csize, SZ_256,
&frame->cr_dmabuf_attachment, &frame->cr_dmabuf_attachment,
&frame->cr_addr, &frame->cr_addr,
&frame->cr_sgt, &frame->cr_sgt,
...@@ -628,7 +636,7 @@ static int tegra_vde_attach_dmabufs_to_frame(struct device *dev, ...@@ -628,7 +636,7 @@ static int tegra_vde_attach_dmabufs_to_frame(struct device *dev,
} }
err = tegra_vde_attach_dmabuf(dev, src->aux_fd, err = tegra_vde_attach_dmabuf(dev, src->aux_fd,
src->aux_offset, csize, src->aux_offset, csize, SZ_256,
&frame->aux_dmabuf_attachment, &frame->aux_dmabuf_attachment,
&frame->aux_addr, &frame->aux_addr,
&frame->aux_sgt, &frame->aux_sgt,
...@@ -677,21 +685,6 @@ static int tegra_vde_validate_frame(struct device *dev, ...@@ -677,21 +685,6 @@ static int tegra_vde_validate_frame(struct device *dev,
return -EINVAL; return -EINVAL;
} }
if (frame->y_offset & 0xFF) {
dev_err(dev, "Bad y_offset 0x%X\n", frame->y_offset);
return -EINVAL;
}
if (frame->cb_offset & 0xFF) {
dev_err(dev, "Bad cb_offset 0x%X\n", frame->cb_offset);
return -EINVAL;
}
if (frame->cr_offset & 0xFF) {
dev_err(dev, "Bad cr_offset 0x%X\n", frame->cr_offset);
return -EINVAL;
}
return 0; return 0;
} }
...@@ -792,7 +785,8 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde *vde, ...@@ -792,7 +785,8 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde *vde,
return ret; return ret;
ret = tegra_vde_attach_dmabuf(dev, ctx.bitstream_data_fd, ret = tegra_vde_attach_dmabuf(dev, ctx.bitstream_data_fd,
ctx.bitstream_data_offset, 0, ctx.bitstream_data_offset,
SZ_16K, SZ_16K,
&bitstream_data_dmabuf_attachment, &bitstream_data_dmabuf_attachment,
&bitstream_data_addr, &bitstream_data_addr,
&bitstream_sgt, &bitstream_sgt,
......
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