fix mut thread crash bug

This commit is contained in:
zsq
2012-04-08 00:00:25 -08:00
parent d19b8ab54d
commit 29ded10bce
7 changed files with 117 additions and 106 deletions

View File

@@ -78,7 +78,7 @@ matrix_cal(const struct rga_req *msg, TILE_INFO *tile)
}
uint32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1)
int32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1)
{
struct rga_req *mp;
@@ -91,9 +91,21 @@ uint32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1)
daw = dah = 0;
mp = msg1;
if(msg->dst.act_w == 0)
{
printk("%s, [%d] rga dst act_w is zero\n", __FUNCTION__, __LINE__);
return -EINVAL;
}
if (msg->dst.act_h == 0)
{
printk("%s, [%d] rga dst act_w is zero\n", __FUNCTION__, __LINE__);
return -EINVAL;
}
w_ratio = (msg->src.act_w << 16) / msg->dst.act_w;
h_ratio = (msg->src.act_h << 16) / msg->dst.act_h;
memcpy(msg1, msg, sizeof(struct rga_req));
msg->dst.format = msg->src.format;
@@ -117,6 +129,10 @@ uint32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1)
msg->src.act_w = (daw - 1) << 3;
}
}
else
{
daw = msg->src.act_w;
}
pl = (RGA_pixel_width_init(msg->src.format));
stride = (pl * daw + 3) & (~3);
@@ -142,6 +158,10 @@ uint32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1)
msg->src.act_h = (dah - 1) << 3;
}
}
else
{
dah = msg->dst.act_h;
}
msg->dst.act_h = dah;
msg->dst.vir_h = dah;

View File

@@ -7,7 +7,7 @@
#define ENABLE 1
#define DISABLE 0
uint32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1);
int32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1);
#endif

View File

@@ -375,6 +375,7 @@ typedef struct rga_service_info {
atomic_t cmd_num;
atomic_t src_format_swt;
int last_prc_src_format;
atomic_t rga_working;
struct mutex mutex; // mutex
} rga_service_info;

View File

@@ -49,7 +49,6 @@
#include "rga_mmu_info.h"
#include "RGA_API.h"
#define RGA_TEST 0
#define RGA_TEST_TIME 0
#define RGA_TEST_FLUSH_TIME 0
@@ -58,7 +57,7 @@
#define PRE_SCALE_BUF_SIZE 2048*1024*4
#define RGA_POWER_OFF_DELAY 4*HZ /* 4s */
#define RGA_TIMEOUT_DELAY 2*HZ /* 2s */
#define RGA_TIMEOUT_DELAY 1*HZ /* 1s */
#define RGA_MAJOR 255
@@ -73,7 +72,7 @@
ktime_t rga_start;
ktime_t rga_end;
int num = 0;
int rga_num = 0;
struct rga_drvdata {
struct miscdevice miscdev;
@@ -260,15 +259,16 @@ static int rga_flush(rga_session *session, unsigned long arg)
ret_timeout = wait_event_interruptible_timeout(session->wait, atomic_read(&session->done), RGA_TIMEOUT_DELAY);
rga_soft_reset();
if (unlikely(ret_timeout < 0)) {
pr_err("flush pid %d wait task ret %d\n", session->pid, ret);
rga_del_running_list();
pr_err("flush pid %d wait task ret %d\n", session->pid, ret);
rga_soft_reset();
ret = -ETIMEDOUT;
} else if (0 == ret_timeout) {
pr_err("flush pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running));
rga_del_running_list();
printk("bus = %.8x\n", rga_read(RGA_INT));
rga_soft_reset();
ret = -ETIMEDOUT;
}
@@ -304,17 +304,16 @@ static int rga_get_result(rga_session *session, unsigned long arg)
static int rga_check_param(const struct rga_req *req)
{
#if 1
/*RGA can support up to 8192*8192 resolution in RGB format,but we limit the image size to 8191*8191 here*/
//check src width and height
if (unlikely((req->src.act_w < 0) || (req->src.act_w > 8191) || (req->src.act_h < 0) || (req->src.act_h > 8191))) {
ERR("invalid source resolution\n");
if (unlikely((req->src.act_w <= 0) || (req->src.act_w > 8191) || (req->src.act_h <= 0) || (req->src.act_h > 8191))) {
ERR("invalid source resolution act_w = %d, act_h = %d\n", req->src.act_w, req->src.act_h);
return -EINVAL;
}
//check dst width and height
if (unlikely((req->dst.act_w < 0) || (req->dst.act_w > 2048) || (req->dst.act_h < 16) || (req->dst.act_h > 2048))) {
ERR("invalid destination resolution\n");
if (unlikely((req->dst.act_w <= 0) || (req->dst.act_w > 2048) || (req->dst.act_h <= 0) || (req->dst.act_h > 2048))) {
ERR("invalid destination resolution act_w = %d, act_h = %d\n", req->dst.act_w, req->dst.act_h);
return -EINVAL;
}
@@ -329,10 +328,7 @@ static int rga_check_param(const struct rga_req *req)
ERR("invalid dst_vir_w\n");
return -EINVAL;
}
#endif
return 0;
}
@@ -385,7 +381,15 @@ static struct rga_reg * rga_reg_init(rga_session *session, struct rga_req *req)
}
}
RGA_gen_reg_info(req, (uint8_t *)reg->cmd_reg);
if(RGA_gen_reg_info(req, (uint8_t *)reg->cmd_reg) == -1)
{
printk("gen reg info error\n");
if(reg != NULL)
{
kfree(reg);
}
return NULL;
}
spin_lock_irqsave(&rga_service.lock, flag);
list_add_tail(&reg->status_link, &rga_service.waiting);
@@ -507,6 +511,7 @@ static void rga_service_session_clear(rga_session *session)
static void rga_try_set_reg(uint32_t num)
{
unsigned long flag;
struct rga_reg *reg ;
if (!num)
{
@@ -522,16 +527,16 @@ static void rga_try_set_reg(uint32_t num)
{
do
{
if((rga_read(RGA_STATUS) & 0x1))
if(!list_empty(&rga_service.running))
{
break;
}
else
{
struct rga_reg *reg = list_entry(rga_service.waiting.next, struct rga_reg, status_link);
/* RGA is idle */
reg = list_entry(rga_service.waiting.next, struct rga_reg, status_link);
rga_soft_reset();
rga_del_running_list();
//rga_del_running_list();
rga_copy_reg(reg, 0);
rga_reg_from_wait_to_run(reg);
@@ -549,31 +554,11 @@ static void rga_try_set_reg(uint32_t num)
/* CMD buff */
rga_write(virt_to_phys(rga_service.cmd_buff) & (~PAGE_MASK), RGA_CMD_ADDR);
#if RGA_TEST
{
uint32_t i, *p;
p = rga_service.cmd_buff;
printk("CMD_REG\n");
for (i=0; i<7; i++)
printk("%.8x %.8x %.8x %.8x\n", p[i*4+0], p[i*4+1], p[i*4+2], p[i*4+3]);
}
#endif
/* master mode */
rga_write(0x1<<2, RGA_SYS_CTRL);
/* All CMD finish int */
rga_write(0x1<<10, RGA_INT);
#if 0
{
uint32_t i;
for(i=0; i<28; i++)
{
rga_write(rga_service.cmd_buff[i], 0x100 + i*4);
}
}
#endif
rga_write((0x1<<10)|(0x1<<8), RGA_INT);
/* Start proc */
atomic_set(&reg->session->done, 0);
@@ -592,9 +577,11 @@ static void rga_try_set_reg(uint32_t num)
}
num--;
}
while(num);
while(0);
}
spin_unlock_irqrestore(&rga_service.lock, flag);
}
@@ -669,20 +656,25 @@ static int rga_blit(rga_session *session, struct rga_req *req)
/* generate 2 cmd for pre scale */
req2 = kmalloc(sizeof(struct rga_req), GFP_KERNEL);
if(NULL == req2) {
return -EINVAL;
return -EFAULT;
}
ret = RGA_gen_two_pro(req, req2);
if(ret == -EINVAL) {
break;
}
ret = rga_check_param(req);
if(ret == -EINVAL) {
printk("req 1 argument is inval\n");
break;
}
ret = rga_check_param(req2);
if(ret == -EINVAL) {
printk("req 2 argument is inval\n");
break;
}
RGA_gen_two_pro(req, req2);
reg = rga_reg_init_2(session, req, req2);
if(reg == NULL) {
@@ -712,7 +704,7 @@ static int rga_blit(rga_session *session, struct rga_req *req)
return 0;
}
while(0);
if(NULL != req2)
{
kfree(req2);
@@ -752,26 +744,24 @@ static int rga_blit_sync(rga_session *session, struct rga_req *req)
ret = rga_blit(session, req);
ret_timeout = wait_event_interruptible_timeout(session->wait, atomic_read(&session->done), RGA_TIMEOUT_DELAY);
rga_soft_reset();
if (unlikely(ret_timeout< 0))
{
pr_err("pid %d wait task ret %d\n", session->pid, ret_timeout);
rga_del_running_list();
pr_err("sync pid %d wait task ret %d\n", session->pid, ret_timeout);
rga_soft_reset();
ret = -ETIMEDOUT;
}
else if (0 == ret_timeout)
{
pr_err("pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running));
rga_del_running_list();
pr_err("sync pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running));
rga_soft_reset();
ret = -ETIMEDOUT;
}
#if RGA_TEST_TIME
rga_end = ktime_get();
rga_end = ktime_sub(rga_end, rga_start);
printk("one cmd end time %d\n", (int)ktime_to_us(rga_end));
printk("sync one cmd end time %d\n", (int)ktime_to_us(rga_end));
#endif
return ret;
@@ -859,8 +849,7 @@ static int rga_open(struct inode *inode, struct file *file)
atomic_set(&session->num_done, 0);
file->private_data = (void *)session;
DBG("*** rga opened by pid %d *** \n", session->pid);
DBG("*** rga dev opened *** \n");
DBG("*** rga dev opened by pid %d *** \n", session->pid);
return nonseekable_open(inode, file);
}
@@ -889,44 +878,39 @@ static int rga_release(struct inode *inode, struct file *file)
kfree(session);
spin_unlock_irqrestore(&rga_service.lock, flag);
pr_debug("dev closed\n");
DBG("*** rga dev close ***\n");
return 0;
}
static irqreturn_t rga_irq(int irq, void *dev_id)
{
//struct rga_reg *reg;
//uint32_t num = 0;
struct list_head *next;
uint32_t flag;
uint32_t i = 0;
//int int_enable = 0;
#if RGA_TEST
printk("rga_irq is valid\n");
#endif
/*clear INT */
rga_write(rga_read(RGA_INT) | (0x1<<6), RGA_INT);
rga_write(rga_read(RGA_INT) | (0x1<<7), RGA_INT);
if(((rga_read(RGA_STATUS) & 0x1) != 0))// idle
if(rga_read(RGA_INT) & 0x1)
{
printk("bus Error interrupt is occur\n");
}
while(((rga_read(RGA_STATUS) & 0x1) != 0) && (i<10))// idle
{
printk(" irq ERROR : RGA is not idle!\n");
rga_soft_reset();
}
rga_soft_reset();
spin_lock(&rga_service.lock);
mdelay(1);
i++;
}
/*clear INT */
rga_write(rga_read(RGA_INT) | (0x1<<6) | (0x1<<7) | (0x1<<4), RGA_INT);
spin_lock_irqsave(&rga_service.lock, flag);
rga_del_running_list();
atomic_set(&rga_service.cmd_num, 0);
spin_unlock(&rga_service.lock);
next = &rga_service.waiting;
if(!list_empty(next))
spin_unlock_irqrestore(&rga_service.lock, flag);
if(!list_empty(&rga_service.waiting))
{
rga_try_set_reg(1);
}
@@ -1245,14 +1229,14 @@ void rga_test_0(void)
dmac_flush_range(&dst_buf[0], &dst_buf[800*480]);
outer_flush_range(virt_to_phys(&dst_buf[0]),virt_to_phys(&dst_buf[800*480]));
#endif
req.src.act_w = 1024;
req.src.act_h = 1024;
req.src.vir_w = 1024;
req.src.vir_h = 1024;
req.src.yrgb_addr = (uint32_t)virt_to_phys(src_buf);
//req.src.uv_addr = (uint32_t)U4200_320_240_swap0;
req.src.uv_addr = req.src.yrgb_addr + 1920;
//req.src.v_addr = (uint32_t)V4200_320_240_swap0;
req.src.format = RK_FORMAT_RGBA_8888;
@@ -1261,28 +1245,30 @@ void rga_test_0(void)
req.dst.vir_w = 1024;
req.dst.vir_h = 1024;
req.dst.x_offset = 0;
req.dst.y_offset = 000;
req.dst.x_offset = 1023;
req.dst.y_offset = 0;
req.dst.yrgb_addr = (uint32_t)virt_to_phys(dst);
//req.dst.format = RK_FORMAT_RGB_565;
req.clip.xmin = 0;
req.clip.xmax = 1023;
req.clip.ymin = 0;
req.clip.ymax = 1023;
//req.render_mode = color_fill_mode;
req.fg_color = 0x80808080;
//req.fg_color = 0x80ffffff;
req.rotate_mode = 0;
req.rotate_mode = 1;
req.scale_mode = 0;
req.alpha_rop_flag = 0;
req.alpha_global_value = 0x80;
req.alpha_rop_flag = 1;
req.alpha_rop_mode = 0x1;
req.sina = 0x00000;
req.cosa = 0x10000;
req.sina = 65536;
req.cosa = 0;
req.mmu_info.mmu_flag = 0;
req.mmu_info.mmu_flag = 0x0;
req.mmu_info.mmu_en = 0;
rga_blit_sync(&session, &req);
@@ -1301,9 +1287,6 @@ void rga_test_0(void)
fb->var.green.msb_right = 0;
fb->var.blue.length = 8;
fb->var.blue.offset = 16;
fb->var.blue.msb_right = 0;

View File

@@ -386,22 +386,19 @@ static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req)
{
/* cal src buf mmu info */
SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr,
req->src.format, req->src.vir_w, (req->src.act_h + req->src.y_offset),
req->src.format, req->src.vir_w, req->src.vir_h,
&SrcStart);
if(SrcMemSize == 0) {
return -EINVAL;
}
/* cal dst buf mmu info */
DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
req->dst.format, req->dst.vir_w, (req->dst.act_h + req->dst.y_offset),
req->dst.format, req->dst.vir_w, req->dst.vir_h,
&DstStart);
if(DstMemSize == 0) {
return -EINVAL;
}
//DstMemSize += 1;
CMDMemSize = 0;
/* cal cmd buf mmu info */
@@ -420,7 +417,7 @@ static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req)
break;
}
MMU_Base = (uint32_t *)kmalloc((AllSize + 1)* sizeof(uint32_t), GFP_KERNEL);
MMU_Base = (uint32_t *)kmalloc((AllSize + 1) * sizeof(uint32_t), GFP_KERNEL);
if(MMU_Base == NULL) {
pr_err("RGA MMU malloc MMU_Base point failed\n");
status = RGA_MALLOC_ERROR;
@@ -1400,6 +1397,7 @@ int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req)
ret = rga_mmu_info_color_palette_mode(reg, req);
break;
case color_fill_mode :
//printk("color_fill_mode is enable\n");
ret = rga_mmu_info_color_fill_mode(reg, req);
break;
case line_point_drawing_mode :
@@ -1409,6 +1407,7 @@ int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req)
ret = rga_mmu_info_blur_sharp_filter_mode(reg, req);
break;
case pre_scaling_mode :
//printk("pre_scaleing_mode is enable\n");
ret = rga_mmu_info_pre_scale_mode(reg, req);
break;
case update_palette_table_mode :

View File

@@ -1290,6 +1290,12 @@ RGA_set_pre_scale_reg_info(u8 *base, const struct rga_req *msg)
dst_width = msg->dst.act_w;
dst_height = msg->dst.act_h;
if((dst_width == 0) || (dst_height == 0))
{
printk("pre scale reg info error ratio is divide zero\n");
return -EINVAL;
}
h_ratio = (src_width <<16) / dst_width;
v_ratio = (src_height<<16) / dst_height;
@@ -1438,7 +1444,7 @@ Author:
Date:
20012-2-2 10:59:25
**************************************************************/
unsigned int
int
RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base)
{
TILE_INFO tile;
@@ -1467,6 +1473,7 @@ RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base)
RGA_set_color_palette_reg_info(base, msg);
break;
case color_fill_mode :
RGA_set_alpha_rop(base, msg);
RGA_set_dst(base, msg);
RGA_set_color(base, msg);
RGA_set_pat(base, msg);
@@ -1486,7 +1493,8 @@ RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base)
case pre_scaling_mode :
RGA_set_src(base, msg);
RGA_set_dst(base, msg);
RGA_set_pre_scale_reg_info(base, msg);
if(RGA_set_pre_scale_reg_info(base, msg) == -EINVAL)
return -1;
break;
case update_palette_table_mode :
if (RGA_set_update_palette_table_reg_info(base, msg)) {

View File

@@ -457,6 +457,6 @@
void matrix_cal(const struct rga_req *msg, TILE_INFO *tile);
unsigned int RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base);
int RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base);
uint8_t RGA_pixel_width_init(uint32_t format);