picdec: memory pollution caused by GE2D [1/1]

PD#OTT-4501

Problem:
the dst canvas phy address for ge2d is overwritten
out of bound before processing

Solution:
alloc canvas index dynamically

Verify:
verified on g12b-w400

Change-Id: If021c087125928d5fb146118432c7ff427ea0dbb
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
This commit is contained in:
Jian Cao
2019-06-11 22:32:22 +08:00
committed by Luan Yuan
parent 65010a3543
commit 0c6cdf7b65

View File

@@ -26,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/canvas/canvas_mgr.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/vfm/vframe_provider.h>
#include <linux/amlogic/media/vfm/vframe_receiver.h>
@@ -64,6 +65,9 @@ static int cma_layout_flag = 1;
#define NO_TASK_MODE
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define aml_pr_info(level, fmt, arg...) \
do { \
if (debug_flag >= level) \
@@ -95,14 +99,6 @@ static int task_running;
#define MAX_VF_POOL_SIZE 2
#define PIC_DEC_CANVAS_START 3
#define PIC_DEC_CANVAS_Y_FRONT (PIC_DEC_CANVAS_START + 1)
#define PIC_DEC_CANVAS_UV_FRONT (PIC_DEC_CANVAS_Y_FRONT + 1)
#define PIC_DEC_CANVAS_Y_BACK (PIC_DEC_CANVAS_UV_FRONT + 1)
#define PIC_DEC_CANVAS_UV_BACK (PIC_DEC_CANVAS_Y_BACK + 1)
#define PIC_DEC_SOURCE_CANVAS (PIC_DEC_CANVAS_UV_BACK + 1)
/*same as tvin pool*/
static int PICDEC_POOL_SIZE = 2;
static int VF_POOL_SIZE = 2;
@@ -148,10 +144,11 @@ static void post_frame(void);
/************************************************
*
* buffer op for video sink.
* 3 canvas id: buffer1 + buffer2 + ge2d_src_buffer
*
************************************************
*/
static int picdec_canvas_table[2];
static int picdec_canvas_table[3];
static inline u32 index2canvas(u32 index)
{
return picdec_canvas_table[index];
@@ -541,7 +538,7 @@ static int picdec_start(void)
unsigned int map_start, map_size = 0;
if (picdec_buffer_init() < 0) {
aml_pr_info(0, "no memory, open fail\n");
aml_pr_info(0, "no memory or canvas resource, open fail\n");
return -1;
}
get_picdec_buf_info(&buf_start, &buf_size, NULL);
@@ -887,22 +884,16 @@ static void rotate_adjust(int w_in, int h_in, int *w_out, int *h_out, int angle)
static int copy_phybuf_to_file(ulong phys, u32 size,
struct file *fp, loff_t pos)
{
u32 i, span = SZ_1M;
u32 count = size / PAGE_ALIGN(span);
ulong addr = phys;
u8 *p;
for (i = 0; i < count; i++) {
addr = phys + i * span;
p = codec_mm_vmap(addr, span);
if (!p)
return -1;
codec_mm_dma_flush(p, span, DMA_FROM_DEVICE);
vfs_write(fp, (char *)p,
span, &pos);
pos += span;
codec_mm_unmap_phyaddr(p);
}
p = codec_mm_vmap(phys, size);
if (!p)
return -1;
codec_mm_dma_flush(p, size, DMA_FROM_DEVICE);
vfs_write(fp, (char *)p,
size, &pos);
codec_mm_unmap_phyaddr(p);
return 0;
}
@@ -910,7 +901,7 @@ int picdec_fill_buffer(struct vframe_s *vf, struct ge2d_context_s *context,
struct config_para_ex_s *ge2d_config)
{
struct canvas_s cs0, cs1, cs2;
int canvas_id = PIC_DEC_SOURCE_CANVAS;
int src_canvas_id = picdec_canvas_table[2];
int canvas_width = (picdec_device.origin_width + 0x1f) & ~0x1f;
int canvas_height = (picdec_device.origin_height + 0xf) & ~0xf;
int frame_width = picdec_input.frame_width;
@@ -923,7 +914,7 @@ int picdec_fill_buffer(struct vframe_s *vf, struct ge2d_context_s *context,
mm_segment_t old_fs = get_fs();
fill_color(vf, context, ge2d_config);
canvas_config(PIC_DEC_SOURCE_CANVAS,
canvas_config(picdec_canvas_table[2],
(ulong)(picdec_device.assit_buf_start),
canvas_width * 3, canvas_height,
CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
@@ -939,9 +930,9 @@ int picdec_fill_buffer(struct vframe_s *vf, struct ge2d_context_s *context,
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0; /* 0xff; */
ge2d_config->dst_xy_swap = 0;
canvas_read((canvas_id & 0xff), &cs0);
canvas_read(((canvas_id >> 8) & 0xff), &cs1);
canvas_read(((canvas_id >> 16) & 0xff), &cs2);
canvas_read((src_canvas_id & 0xff), &cs0);
canvas_read(((src_canvas_id >> 8) & 0xff), &cs1);
canvas_read(((src_canvas_id >> 16) & 0xff), &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
@@ -956,7 +947,7 @@ int picdec_fill_buffer(struct vframe_s *vf, struct ge2d_context_s *context,
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = PIC_DEC_SOURCE_CANVAS;
ge2d_config->src_para.canvas_index = src_canvas_id;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FORMAT_S24_BGR;
ge2d_config->src_para.fill_color_en = 0;
@@ -1229,6 +1220,7 @@ int picdec_cma_buf_init(void)
picdec_device.buffer_size = (48*SZ_1M);
}
}
aml_pr_info(0, "cma memory is %x , size is %x\n",
(unsigned int)picdec_device.buffer_start,
(unsigned int)picdec_device.buffer_size);
@@ -1326,30 +1318,52 @@ int picdec_buffer_init(void)
canvas_height = (picdec_device.disp_height + 0xf) & ~0xf;
decbuf_size = canvas_width * canvas_height;
if (picdec_device.output_format_mode) {
u32 canvas_table[3];
if (canvas_pool_alloc_canvas_table("picdec", canvas_table,
ARRAY_SIZE(canvas_table),
CANVAS_MAP_TYPE_1)) {
pr_err("%s allocate canvas error.\n", __func__);
return -1;
}
aml_pr_info(0, "canvas alloced id, %u~%u~%u.\n",
canvas_table[0], canvas_table[1], canvas_table[2]);
for (i = 0; i < MAX_VF_POOL_SIZE; i++) {
canvas_config(PIC_DEC_CANVAS_START + i,
canvas_config(canvas_table[i],
(unsigned int)(buf_start + offset),
canvas_width * 3,
canvas_height,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_LINEAR);
offset = canvas_width * canvas_height * 3;
picdec_canvas_table[i] =
PIC_DEC_CANVAS_START + i;
picdec_canvas_table[i] = canvas_table[i];
vfbuf_use[i] = 0;
}
picdec_canvas_table[i] = canvas_table[i];
} else {
u32 canvas_table[5];
if (canvas_pool_alloc_canvas_table("picdec", canvas_table,
ARRAY_SIZE(canvas_table),
CANVAS_MAP_TYPE_1)) {
pr_err("%s allocate canvas error.\n", __func__);
return -1;
}
aml_pr_info(0, "canvas alloced id, %u~%u~%u.\n",
canvas_table[0], canvas_table[1], canvas_table[2]);
for (i = 0; i < MAX_VF_POOL_SIZE; i++) {
pr_info("%d addr is %x################\n",
i, (unsigned int)(buf_start + offset));
canvas_config(PIC_DEC_CANVAS_START + 2 * i,
canvas_config(canvas_table[2 * i],
(unsigned int)(buf_start + offset),
canvas_width,
canvas_height,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_LINEAR);
offset += canvas_width * canvas_height;
canvas_config(PIC_DEC_CANVAS_START + 2 * i + 1,
canvas_config(canvas_table[2 * i + 1],
(unsigned int)(buf_start + offset),
canvas_width,
canvas_height / 2,
@@ -1357,10 +1371,11 @@ int picdec_buffer_init(void)
CANVAS_BLKMODE_LINEAR);
offset += canvas_width * canvas_height / 2;
picdec_canvas_table[i] =
(PIC_DEC_CANVAS_START + 2 * i) |
((PIC_DEC_CANVAS_START + 2 * i + 1) << 8);
(canvas_table[2 * i] |
(canvas_table[2 * i + 1] << 8));
vfbuf_use[i] = 0;
}
picdec_canvas_table[i] = canvas_table[2 * i];
}
if (picdec_device.output_format_mode)
@@ -1601,6 +1616,7 @@ static int picdec_release(struct inode *inode, struct file *file)
{
struct ge2d_context_s *context;
struct picdec_private_s *priv = file->private_data;
int i;
if (!cma_layout_flag)
context = (struct ge2d_context_s *) file->private_data;
@@ -1617,6 +1633,22 @@ static int picdec_release(struct inode *inode, struct file *file)
kfree(priv);
priv = NULL;
}
for (i = 0; i < ARRAY_SIZE(picdec_canvas_table); i++) {
if (picdec_canvas_table[i]) {
if (picdec_canvas_table[i] & 0xff)
canvas_pool_map_free_canvas(
picdec_canvas_table[i] & 0xff);
if ((picdec_canvas_table[i] >> 8) & 0xff)
canvas_pool_map_free_canvas(
(picdec_canvas_table[i] >> 8) & 0xff);
if ((picdec_canvas_table[i] >> 16) & 0xff)
canvas_pool_map_free_canvas(
(picdec_canvas_table[i] >> 16) & 0xff);
}
picdec_canvas_table[i] = 0;
}
aml_pr_info(0, "release one picdec device\n");
return -1;
}