Commit 1af21985 authored by Marek Szyprowski's avatar Marek Szyprowski Committed by Mauro Carvalho Chehab

[media] s5p-mfc: add additional check for incorrect memory configuration

MFC hardware is known to trash random memory if one tries to use a
buffer which has lower DMA addresses than the configured DMA base
address. This patch adds a check for this case and proper error
handling.
Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Acked-by: default avatarKamil Debski <kamil@wypas.org>
[s.nawrocki@samsung.com: fixed typo (addres -> address]
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 490a977a
...@@ -37,10 +37,9 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev) ...@@ -37,10 +37,9 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev)
dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev); dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev);
} }
int s5p_mfc_alloc_priv_buf(struct device *dev, int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base,
struct s5p_mfc_priv_buf *b) struct s5p_mfc_priv_buf *b)
{ {
mfc_debug(3, "Allocating priv: %zu\n", b->size); mfc_debug(3, "Allocating priv: %zu\n", b->size);
b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL); b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL);
...@@ -50,6 +49,14 @@ int s5p_mfc_alloc_priv_buf(struct device *dev, ...@@ -50,6 +49,14 @@ int s5p_mfc_alloc_priv_buf(struct device *dev,
return -ENOMEM; return -ENOMEM;
} }
if (b->dma < base) {
mfc_err("Invaling memory configuration!\n");
mfc_err("Allocated buffer (%pad) is lower than memory base address (%pad)\n",
&b->dma, &base);
dma_free_coherent(dev, b->size, b->virt, b->dma);
return -ENOMEM;
}
mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma); mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma);
return 0; return 0;
} }
......
...@@ -334,7 +334,7 @@ struct s5p_mfc_hw_ops { ...@@ -334,7 +334,7 @@ struct s5p_mfc_hw_ops {
void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
void s5p_mfc_init_regs(struct s5p_mfc_dev *dev); void s5p_mfc_init_regs(struct s5p_mfc_dev *dev);
int s5p_mfc_alloc_priv_buf(struct device *dev, int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base,
struct s5p_mfc_priv_buf *b); struct s5p_mfc_priv_buf *b);
void s5p_mfc_release_priv_buf(struct device *dev, void s5p_mfc_release_priv_buf(struct device *dev,
struct s5p_mfc_priv_buf *b); struct s5p_mfc_priv_buf *b);
......
...@@ -41,7 +41,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) ...@@ -41,7 +41,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
int ret; int ret;
ctx->dsc.size = buf_size->dsc; ctx->dsc.size = buf_size->dsc;
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->dsc); ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->dsc);
if (ret) { if (ret) {
mfc_err("Failed to allocate temporary buffer\n"); mfc_err("Failed to allocate temporary buffer\n");
return ret; return ret;
...@@ -172,7 +172,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) ...@@ -172,7 +172,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
/* Allocate only if memory from bank 1 is necessary */ /* Allocate only if memory from bank 1 is necessary */
if (ctx->bank1.size > 0) { if (ctx->bank1.size > 0) {
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1,
&ctx->bank1);
if (ret) { if (ret) {
mfc_err("Failed to allocate Bank1 temporary buffer\n"); mfc_err("Failed to allocate Bank1 temporary buffer\n");
return ret; return ret;
...@@ -181,7 +182,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) ...@@ -181,7 +182,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
} }
/* Allocate only if memory from bank 2 is necessary */ /* Allocate only if memory from bank 2 is necessary */
if (ctx->bank2.size > 0) { if (ctx->bank2.size > 0) {
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, &ctx->bank2); ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, dev->bank2,
&ctx->bank2);
if (ret) { if (ret) {
mfc_err("Failed to allocate Bank2 temporary buffer\n"); mfc_err("Failed to allocate Bank2 temporary buffer\n");
s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1);
...@@ -212,7 +214,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) ...@@ -212,7 +214,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
else else
ctx->ctx.size = buf_size->non_h264_ctx; ctx->ctx.size = buf_size->non_h264_ctx;
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->ctx);
if (ret) { if (ret) {
mfc_err("Failed to allocate instance buffer\n"); mfc_err("Failed to allocate instance buffer\n");
return ret; return ret;
...@@ -225,7 +227,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) ...@@ -225,7 +227,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
/* Initialize shared memory */ /* Initialize shared memory */
ctx->shm.size = buf_size->shm; ctx->shm.size = buf_size->shm;
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->shm); ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->shm);
if (ret) { if (ret) {
mfc_err("Failed to allocate shared memory buffer\n"); mfc_err("Failed to allocate shared memory buffer\n");
s5p_mfc_release_priv_buf(dev->mem_dev_l, &ctx->ctx); s5p_mfc_release_priv_buf(dev->mem_dev_l, &ctx->ctx);
......
...@@ -239,7 +239,8 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) ...@@ -239,7 +239,8 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
/* Allocate only if memory from bank 1 is necessary */ /* Allocate only if memory from bank 1 is necessary */
if (ctx->bank1.size > 0) { if (ctx->bank1.size > 0) {
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1,
&ctx->bank1);
if (ret) { if (ret) {
mfc_err("Failed to allocate Bank1 memory\n"); mfc_err("Failed to allocate Bank1 memory\n");
return ret; return ret;
...@@ -291,7 +292,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) ...@@ -291,7 +292,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
break; break;
} }
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->ctx);
if (ret) { if (ret) {
mfc_err("Failed to allocate instance buffer\n"); mfc_err("Failed to allocate instance buffer\n");
return ret; return ret;
...@@ -320,7 +321,8 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) ...@@ -320,7 +321,8 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
mfc_debug_enter(); mfc_debug_enter();
dev->ctx_buf.size = buf_size->dev_ctx; dev->ctx_buf.size = buf_size->dev_ctx;
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &dev->ctx_buf); ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1,
&dev->ctx_buf);
if (ret) { if (ret) {
mfc_err("Failed to allocate device context buffer\n"); mfc_err("Failed to allocate device context buffer\n");
return ret; return ret;
......
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