From: Yong He <yong.m...@intel.com>
Subject: [PATCH] MRST Tablet camera driver ver-0.962, fix 10803

Bug 10803 - Crash when closing the driver

when camera driver issue an i2c read, the i2c driver uses local var as w/r 
buffers (in stack)
the driver will wait for the i2c ops completion IRQ,
then the i2c ISR write the hw received data to the caller buffer.
when user kill the caller program at the IRQ waiting moment,
the read buffer may got freed before the i2c completion IRQ
happens, that will lead to invalid access.

the solution is to use global static var as the i2c w/r buffer,
so that it won't be invalid even user killed the app.

Signed-off-by: Yong He <yong.m...@intel.com>
Index: linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c
===================================================================
--- linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c        
(revision 143)
+++ linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c     (working 
copy)
@@ -50,7 +50,7 @@
#include "ci_sensor_common.h"
#include "ov5640.h"
-#define DRIVER_VERSION "0.961"
+#define DRIVER_VERSION "0.962"
 #define GPIO_FLASH 45
static int ov5640_flash;
@@ -193,6 +193,7 @@
 #define RESOLUTION_INDEX_VGA 6
#define RESOLUTION_INDEX_720P 4
+#define RESOLUTION_INDEX_QXGA_PLUS 0
#define OV5640_FW_INITED 1
#define OV5640_FW_RESET 0
@@ -241,56 +242,59 @@
/*
  * I2C Read & Write stuff
  */
+static u8 i2c_read_buf[8];
+static struct i2c_msg msg_rd[2];
+static u8 msgbuf_rd[2];
+
static int ov5640_read(struct i2c_client *c, u16 reg, u8 *value)
{
       int ret;
       int i;
-        struct i2c_msg msg[2];
-        u8 msgbuf[2];
-        u8 ret_val = 0;
+
       *value = 0;
       /* Read needs two message to go */
-        memset(&msg, 0, sizeof(msg));
-        msgbuf[0] = 0;
-        msgbuf[1] = 0;
+       memset(&msg_rd, 0, sizeof(msg_rd));
+       msgbuf_rd[0] = 0;
+       msgbuf_rd[1] = 0;
       i = 0;
-        msgbuf[i++] = reg >> 8;
-        msgbuf[i++] = reg;
-        msg[0].addr = c->addr;
-        msg[0].buf = msgbuf;
-        msg[0].len = i;
+       msgbuf_rd[i++] = reg >> 8;
+       msgbuf_rd[i++] = reg;
+       msg_rd[0].addr = c->addr;
+       msg_rd[0].buf = msgbuf_rd;
+       msg_rd[0].len = i;
-        msg[1].addr = c->addr;
-        msg[1].flags = I2C_M_RD;
-        msg[1].buf = &ret_val;
-        msg[1].len = 1;
+       msg_rd[1].addr = c->addr;
+       msg_rd[1].flags = I2C_M_RD;
+       msg_rd[1].buf = i2c_read_buf;
+       msg_rd[1].len = 1;
-        ret = i2c_transfer(c->adapter, &msg[0], 2);
-        *value = ret_val;
+       ret = i2c_transfer(c->adapter, &msg_rd[0], 2);
+       *value = i2c_read_buf[0];
        ret = (ret == 2) ? 0 : -1;
       return ret;
}
+static struct i2c_msg msg_wr;
+static u8 msgbuf_wr[3];
+
static int ov5640_write(struct i2c_client *c, u16 reg, u8 value)
{
       int ret, i;
-        struct i2c_msg msg;
-        u8 msgbuf[3];
        /* Writing only needs one message */
-        memset(&msg, 0, sizeof(msg));
+       memset(&msg_wr, 0, sizeof(msg_wr));
       i = 0;
-        msgbuf[i++] = reg >> 8;
-        msgbuf[i++] = reg;
-        msgbuf[i++] = value;
+       msgbuf_wr[i++] = reg >> 8;
+       msgbuf_wr[i++] = reg;
+       msgbuf_wr[i++] = value;
-        msg.addr = c->addr;
-        msg.flags = 0;
-        msg.buf = msgbuf;
-        msg.len = i;
+       msg_wr.addr = c->addr;
+       msg_wr.flags = 0;
+       msg_wr.buf = msgbuf_wr;
+       msg_wr.len = i;
-        ret = i2c_transfer(c->adapter, &msg, 1);
+       ret = i2c_transfer(c->adapter, &msg_wr, 1);
        /* If this is a reset register, wait for 1ms */
       if (reg == 0x3008 && (value & 0x80))
@@ -2458,11 +2462,14 @@
                                            " <----------- set stream on, sleep 
300 ms"
                                            " for sensor adjusting...\n");
                          ov5640_write(client, 0x3008, 0x02);
-                           ov5640_set_aec_agc(client, 1);
-                           af_fw_status = ov5640_af_init(client);
-                           if (af_fw_status != 0) {
-                                    dev_dbg(sd->v4l2_dev->dev, "ov5640_af_init 
error - (%d)\n",
+                          /* When taking snapshot, hold the calculated 
Gain/Exposure */
+                          if (ov5640_status.current_res_i != 
RESOLUTION_INDEX_QXGA_PLUS) {
+                                   ov5640_set_aec_agc(client, 1);
+                                   af_fw_status = ov5640_af_init(client);
+                                   if (af_fw_status != 0) {
+                                            dev_dbg(sd->v4l2_dev->dev, 
"ov5640_af_init error - (%d)\n",
                                                      af_fw_status);
+                                   }
                          }
                          msleep(50);
                }
Index: linux-2.6.37/drivers/staging/mrstci/mrstov9740/mrstov9740.c
===================================================================
--- linux-2.6.37/drivers/staging/mrstci/mrstov9740/mrstov9740.c        
(revision 143)
+++ linux-2.6.37/drivers/staging/mrstci/mrstov9740/mrstov9740.c     (working 
copy)
@@ -47,7 +47,7 @@
#include "ci_sensor_common.h"
#include "ov9740.h"
-#define DRIVER_VERSION "0.961"
+#define DRIVER_VERSION "0.962"
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #define DBG_entering  pr_debug("%s entering", __func__);
@@ -181,56 +181,59 @@
/*
  * I2C Read & Write stuff
  */
+static u8 i2c_read_buf;
+static struct i2c_msg msg_rd[2];
+static u8 msgbuf_rd[2];
+
static int ov9740_read(struct i2c_client *c, u16 reg, u8 *value)
{
       int ret;
       int i;
-        struct i2c_msg msg[2];
-        u8 msgbuf[2];
-        u8 ret_val = 0;
+       i2c_read_buf = 0;
       *value = 0;
       /* Read needs two message to go */
-        memset(&msg, 0, sizeof(msg));
-        msgbuf[0] = 0;
-        msgbuf[1] = 0;
+       memset(&msg_rd, 0, sizeof(msg_rd));
+       msgbuf_rd[0] = 0;
+       msgbuf_rd[1] = 0;
       i = 0;
-        msgbuf[i++] = reg >> 8;
-        msgbuf[i++] = reg;
-        msg[0].addr = c->addr;
-        msg[0].buf = msgbuf;
-        msg[0].len = i;
+       msgbuf_rd[i++] = reg >> 8;
+       msgbuf_rd[i++] = reg;
+       msg_rd[0].addr = c->addr;
+       msg_rd[0].buf = msgbuf_rd;
+       msg_rd[0].len = i;
-        msg[1].addr = c->addr;
-        msg[1].flags = I2C_M_RD;
-        msg[1].buf = &ret_val;
-        msg[1].len = 1;
+       msg_rd[1].addr = c->addr;
+       msg_rd[1].flags = I2C_M_RD;
+       msg_rd[1].buf = &i2c_read_buf;
+       msg_rd[1].len = 1;
-        ret = i2c_transfer(c->adapter, &msg[0], 2);
-        *value = ret_val;
+       ret = i2c_transfer(c->adapter, &msg_rd[0], 2);
+       *value = i2c_read_buf;
        ret = (ret == 2) ? 0 : -1;
       return ret;
}
+static struct i2c_msg msg_wr;
+static u8 msgbuf_wr[3];
+
static int ov9740_write(struct i2c_client *c, u16 reg, u8 value)
{
       int ret, i;
-        struct i2c_msg msg;
-        u8 msgbuf[3];
        /* Writing only needs one message */
-        memset(&msg, 0, sizeof(msg));
+       memset(&msg_wr, 0, sizeof(msg_wr));
       i = 0;
-        msgbuf[i++] = reg >> 8;
-        msgbuf[i++] = reg;
-        msgbuf[i++] = value;
+       msgbuf_wr[i++] = reg >> 8;
+       msgbuf_wr[i++] = reg;
+       msgbuf_wr[i++] = value;
-        msg.addr = c->addr;
-        msg.flags = 0;
-        msg.buf = msgbuf;
-        msg.len = i;
+       msg_wr.addr = c->addr;
+       msg_wr.flags = 0;
+       msg_wr.buf = msgbuf_wr;
+       msg_wr.len = i;
-        ret = i2c_transfer(c->adapter, &msg, 1);
+       ret = i2c_transfer(c->adapter, &msg_wr, 1);
        /* If this is a reset register, wait for 1ms */
       if (reg == 0x3012 && (value & 0x80))

Best Regards,

Yong He
Software Engineer, PCSD SW Solutions,
Intel Asia-Pacific R&D Ltd.
Phone (+86) 21-61166334
Lab (+86) 21-61167881

Attachment: linux-2.6.37-camera-ov5640-ov9740-version-0.961_to_0.962.patch
Description: linux-2.6.37-camera-ov5640-ov9740-version-0.961_to_0.962.patch

_______________________________________________
MeeGo-kernel mailing list
MeeGo-kernel@lists.meego.com
http://lists.meego.com/listinfo/meego-kernel

Reply via email to