Merge "msm: camera: Fix memory leak with stats buffers" into msm-3.4
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 67e7c02..bb7db54 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -673,7 +673,6 @@
}
case MSM_CAM_IOCTL_STATS_ENQUEUEBUF: {
struct msm_stats_buf_info buf_info;
-
if (copy_from_user(&buf_info, arg,
sizeof(struct msm_stats_buf_info))) {
ERR_COPY_FROM_USER();
@@ -687,18 +686,30 @@
}
case MSM_CAM_IOCTL_STATS_FLUSH_BUFQ: {
struct msm_stats_flush_bufq bufq_info;
-
if (copy_from_user(&bufq_info, arg,
sizeof(struct msm_stats_flush_bufq))) {
ERR_COPY_FROM_USER();
return -EFAULT;
- }
+ }
cfgcmd.cmd_type = VFE_CMD_STATS_FLUSH_BUFQ;
cfgcmd.value = (void *)&bufq_info;
cfgcmd.length = sizeof(struct msm_stats_flush_bufq);
rc = msm_isp_subdev_ioctl(sd, &cfgcmd, NULL);
break;
}
+ case MSM_CAM_IOCTL_STATS_UNREG_BUF: {
+ struct msm_stats_reqbuf reqbuf;
+ if (copy_from_user(&reqbuf, arg,
+ sizeof(struct msm_stats_reqbuf))) {
+ ERR_COPY_FROM_USER();
+ return -EFAULT;
+ }
+ cfgcmd.cmd_type = VFE_CMD_STATS_UNREGBUF;
+ cfgcmd.value = (void *)&reqbuf;
+ cfgcmd.length = sizeof(struct msm_stats_reqbuf);
+ rc = msm_isp_subdev_ioctl(sd, &cfgcmd, (void *)mctl->client);
+ break;
+ }
default:
rc = -1;
break;
@@ -734,6 +745,7 @@
case MSM_CAM_IOCTL_STATS_REQBUF:
case MSM_CAM_IOCTL_STATS_ENQUEUEBUF:
case MSM_CAM_IOCTL_STATS_FLUSH_BUFQ:
+ case MSM_CAM_IOCTL_STATS_UNREG_BUF:
rc = msm_vfe_stats_buf_ioctl(sd, cmd, pmctl, argp);
break;
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index 18168ee..a22a09f 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -417,6 +417,25 @@
return 0L;
}
+static unsigned long vfe31_stats_unregbuf(
+ struct msm_stats_reqbuf *req_buf)
+{
+ int i = 0, rc = 0;
+
+ for (i = 0; i < req_buf->num_buf; i++) {
+ rc = vfe31_ctrl->stats_ops.buf_unprepare(
+ vfe31_ctrl->stats_ops.stats_ctrl,
+ req_buf->stats_type, i,
+ vfe31_ctrl->stats_ops.client);
+ if (rc < 0) {
+ pr_err("%s: unreg stats buf (type = %d) err = %d",
+ __func__, req_buf->stats_type, rc);
+ return rc;
+ }
+ }
+ return 0L;
+}
+
static int vfe_stats_awb_buf_init(
struct vfe_cmd_stats_buf *in)
{
@@ -3334,6 +3353,22 @@
vfe31_ctrl->stats_ops.client);
}
break;
+ case VFE_CMD_STATS_UNREGBUF:
+ {
+ struct msm_stats_reqbuf *req_buf = NULL;
+ req_buf = (struct msm_stats_reqbuf *)cmd->value;
+ if (sizeof(struct msm_stats_reqbuf) != cmd->length) {
+ /* error. the length not match */
+ pr_err("%s: stats reqbuf input size = %d,\n"
+ "struct size = %d, mitch match\n",
+ __func__, cmd->length,
+ sizeof(struct msm_stats_reqbuf));
+ rc = -EINVAL ;
+ goto end;
+ }
+ rc = vfe31_stats_unregbuf(req_buf);
+ }
+ break;
default:
rc = -1;
pr_err("%s: cmd_type %d not supported", __func__,
@@ -3583,6 +3618,7 @@
case VFE_CMD_STATS_REQBUF:
case VFE_CMD_STATS_ENQUEUEBUF:
case VFE_CMD_STATS_FLUSH_BUFQ:
+ case VFE_CMD_STATS_UNREGBUF:
/* for easy porting put in one envelope */
rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data);
return rc;
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index aa2b19d..f748b8d 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -216,6 +216,26 @@
{VFE_CMD_GET_RGB_G_TABLE},
{VFE_CMD_GET_LA_TABLE},
{VFE_CMD_DEMOSAICV3_UPDATE},
+ {VFE_CMD_ACTIVE_REGION_CFG},
+/*130*/ {VFE_CMD_COLOR_PROCESSING_CONFIG},
+ {VFE_CMD_STATS_WB_AEC_CONFIG},
+ {VFE_CMD_STATS_WB_AEC_UPDATE},
+ {VFE_CMD_Y_GAMMA_CONFIG},
+ {VFE_CMD_SCALE_OUTPUT1_CONFIG},
+/*135*/ {VFE_CMD_SCALE_OUTPUT2_CONFIG},
+ {VFE_CMD_CAPTURE_RAW},
+ {VFE_CMD_STOP_LIVESHOT},
+ {VFE_CMD_RECONFIG_VFE},
+ {VFE_CMD_STATS_REQBUF},
+/*140*/ {VFE_CMD_STATS_ENQUEUEBUF},
+ {VFE_CMD_STATS_FLUSH_BUFQ},
+ {VFE_CMD_STATS_UNREGBUF},
+
+
+
+
+
+
};
uint32_t vfe32_AXI_WM_CFG[] = {
@@ -677,6 +697,26 @@
return 0L;
}
+
+static unsigned long vfe32_stats_unregbuf(
+ struct vfe32_ctrl_type *vfe32_ctrl,
+ struct msm_stats_reqbuf *req_buf)
+{
+ int i = 0, rc = 0;
+
+ for (i = 0; i < req_buf->num_buf; i++) {
+ rc = vfe32_ctrl->stats_ops.buf_unprepare(
+ vfe32_ctrl->stats_ops.stats_ctrl,
+ req_buf->stats_type, i,
+ vfe32_ctrl->stats_ops.client);
+ if (rc < 0) {
+ pr_err("%s: unreg stats buf (type = %d) err = %d",
+ __func__, req_buf->stats_type, rc);
+ return rc;
+ }
+ }
+ return 0L;
+}
static int vfe_stats_awb_buf_init(
struct vfe32_ctrl_type *vfe32_ctrl,
struct vfe_cmd_stats_buf *in)
@@ -4521,6 +4561,22 @@
vfe_ctrl->stats_ops.client);
}
break;
+ case VFE_CMD_STATS_UNREGBUF:
+ {
+ struct msm_stats_reqbuf *req_buf = NULL;
+ req_buf = (struct msm_stats_reqbuf *)cmd->value;
+ if (sizeof(struct msm_stats_reqbuf) != cmd->length) {
+ /* error. the length not match */
+ pr_err("%s: stats reqbuf input size = %d,\n"
+ "struct size = %d, mitch match\n",
+ __func__, cmd->length,
+ sizeof(struct msm_stats_reqbuf));
+ rc = -EINVAL ;
+ goto end;
+ }
+ rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf);
+ }
+ break;
default:
rc = -1;
pr_err("%s: cmd_type %d not supported", __func__,
@@ -4570,6 +4626,7 @@
case VFE_CMD_STATS_REQBUF:
case VFE_CMD_STATS_ENQUEUEBUF:
case VFE_CMD_STATS_FLUSH_BUFQ:
+ case VFE_CMD_STATS_UNREGBUF:
/* for easy porting put in one envelope */
rc = vfe_stats_bufq_sub_ioctl(vfe32_ctrl,
cmd, vfe_params->data);
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 64e0385..59c5d7d 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -404,6 +404,25 @@
return 0L;
}
+static unsigned long vfe2x_stats_unregbuf(
+ struct msm_stats_reqbuf *req_buf)
+{
+ int i = 0, rc = 0;
+
+ for (i = 0; i < req_buf->num_buf; i++) {
+ rc = vfe2x_ctrl->stats_ops.buf_unprepare(
+ vfe2x_ctrl->stats_ops.stats_ctrl,
+ req_buf->stats_type, i,
+ vfe2x_ctrl->stats_ops.client);
+ if (rc < 0) {
+ pr_err("%s: unreg stats buf (type = %d) err = %d",
+ __func__, req_buf->stats_type, rc);
+ return rc;
+ }
+ }
+ return 0L;
+}
+
static int vfe2x_stats_buf_init(enum msm_stats_enum_type type)
{
unsigned long flags;
@@ -556,6 +575,22 @@
vfe2x_ctrl->stats_ops.client);
}
break;
+ case VFE_CMD_STATS_UNREGBUF:
+ {
+ struct msm_stats_reqbuf *req_buf = NULL;
+ req_buf = (struct msm_stats_reqbuf *)cmd->value;
+ if (sizeof(struct msm_stats_reqbuf) != cmd->length) {
+ /* error. the length not match */
+ pr_err("%s: stats reqbuf input size = %d,\n"
+ "struct size = %d, mitch match\n",
+ __func__, cmd->length,
+ sizeof(struct msm_stats_reqbuf));
+ rc = -EINVAL ;
+ goto end;
+ }
+ rc = vfe2x_stats_unregbuf(req_buf);
+ }
+ break;
default:
rc = -1;
pr_err("%s: cmd_type %d not supported",
@@ -1228,6 +1263,7 @@
cmd->cmd_type != CMD_VFE_BUFFER_RELEASE &&
cmd->cmd_type != VFE_CMD_STATS_REQBUF &&
cmd->cmd_type != VFE_CMD_STATS_FLUSH_BUFQ &&
+ cmd->cmd_type != VFE_CMD_STATS_UNREGBUF &&
cmd->cmd_type != VFE_CMD_STATS_ENQUEUEBUF) {
if (copy_from_user(&vfecmd,
(void __user *)(cmd->value),
@@ -1239,6 +1275,7 @@
switch (cmd->cmd_type) {
case VFE_CMD_STATS_REQBUF:
case VFE_CMD_STATS_FLUSH_BUFQ:
+ case VFE_CMD_STATS_UNREGBUF:
/* for easy porting put in one envelope */
rc = vfe2x_stats_bufq_sub_ioctl(cmd, vfe_params->data);
return rc;
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index ae81dcd..a7ae2cc 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -213,6 +213,10 @@
#define MSM_CAM_IOCTL_GET_INST_HANDLE \
_IOR(MSM_CAM_IOCTL_MAGIC, 60, uint32_t *)
+#define MSM_CAM_IOCTL_STATS_UNREG_BUF \
+ _IOR(MSM_CAM_IOCTL_MAGIC, 61, struct msm_stats_flush_bufq *)
+
+
struct msm_stats_reqbuf {
int num_buf; /* how many buffers requested */
int stats_type; /* stats type */
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 3df6ded..8de8c37 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -206,6 +206,7 @@
#define VFE_CMD_STATS_REQBUF 139
#define VFE_CMD_STATS_ENQUEUEBUF 140
#define VFE_CMD_STATS_FLUSH_BUFQ 141
+#define VFE_CMD_STATS_UNREGBUF 142
struct msm_isp_cmd {
int32_t id;