Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Kamil Debski <kamil@wypas.org>
[s.nawrocki@samsung.com: fixed typo (addres -> address]
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

authored by

Marek Szyprowski and committed by
Mauro Carvalho Chehab
1af21985 490a977a

+22 -11
+9 -2
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
··· 37 37 dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev); 38 38 } 39 39 40 - int s5p_mfc_alloc_priv_buf(struct device *dev, 40 + int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base, 41 41 struct s5p_mfc_priv_buf *b) 42 42 { 43 - 44 43 mfc_debug(3, "Allocating priv: %zu\n", b->size); 45 44 46 45 b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL); 47 46 48 47 if (!b->virt) { 49 48 mfc_err("Allocating private buffer failed\n"); 49 + return -ENOMEM; 50 + } 51 + 52 + if (b->dma < base) { 53 + mfc_err("Invaling memory configuration!\n"); 54 + mfc_err("Allocated buffer (%pad) is lower than memory base address (%pad)\n", 55 + &b->dma, &base); 56 + dma_free_coherent(dev, b->size, b->virt, b->dma); 50 57 return -ENOMEM; 51 58 } 52 59
+1 -1
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
··· 334 334 335 335 void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); 336 336 void s5p_mfc_init_regs(struct s5p_mfc_dev *dev); 337 - int s5p_mfc_alloc_priv_buf(struct device *dev, 337 + int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base, 338 338 struct s5p_mfc_priv_buf *b); 339 339 void s5p_mfc_release_priv_buf(struct device *dev, 340 340 struct s5p_mfc_priv_buf *b);
+7 -5
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
··· 41 41 int ret; 42 42 43 43 ctx->dsc.size = buf_size->dsc; 44 - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->dsc); 44 + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->dsc); 45 45 if (ret) { 46 46 mfc_err("Failed to allocate temporary buffer\n"); 47 47 return ret; ··· 172 172 /* Allocate only if memory from bank 1 is necessary */ 173 173 if (ctx->bank1.size > 0) { 174 174 175 - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); 175 + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, 176 + &ctx->bank1); 176 177 if (ret) { 177 178 mfc_err("Failed to allocate Bank1 temporary buffer\n"); 178 179 return ret; ··· 182 181 } 183 182 /* Allocate only if memory from bank 2 is necessary */ 184 183 if (ctx->bank2.size > 0) { 185 - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, &ctx->bank2); 184 + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, dev->bank2, 185 + &ctx->bank2); 186 186 if (ret) { 187 187 mfc_err("Failed to allocate Bank2 temporary buffer\n"); 188 188 s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); ··· 214 212 else 215 213 ctx->ctx.size = buf_size->non_h264_ctx; 216 214 217 - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); 215 + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->ctx); 218 216 if (ret) { 219 217 mfc_err("Failed to allocate instance buffer\n"); 220 218 return ret; ··· 227 225 228 226 /* Initialize shared memory */ 229 227 ctx->shm.size = buf_size->shm; 230 - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->shm); 228 + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->shm); 231 229 if (ret) { 232 230 mfc_err("Failed to allocate shared memory buffer\n"); 233 231 s5p_mfc_release_priv_buf(dev->mem_dev_l, &ctx->ctx);
+5 -3
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
··· 239 239 240 240 /* Allocate only if memory from bank 1 is necessary */ 241 241 if (ctx->bank1.size > 0) { 242 - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); 242 + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, 243 + &ctx->bank1); 243 244 if (ret) { 244 245 mfc_err("Failed to allocate Bank1 memory\n"); 245 246 return ret; ··· 292 291 break; 293 292 } 294 293 295 - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); 294 + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->ctx); 296 295 if (ret) { 297 296 mfc_err("Failed to allocate instance buffer\n"); 298 297 return ret; ··· 321 320 mfc_debug_enter(); 322 321 323 322 dev->ctx_buf.size = buf_size->dev_ctx; 324 - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &dev->ctx_buf); 323 + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, 324 + &dev->ctx_buf); 325 325 if (ret) { 326 326 mfc_err("Failed to allocate device context buffer\n"); 327 327 return ret;