Merge "msm: camera: Cleanup msm generic buf queue on userspace crash"
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index efa3ad0..c79b3a3 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -438,7 +438,7 @@
 static inline int __msm_destroy_session_streams(void *d1, void *d2)
 {
 	struct msm_stream *stream = d1;
-
+	pr_err("%s: Destroyed here due to list is not empty\n", __func__);
 	INIT_LIST_HEAD(&stream->queued_list);
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 154ee87..7520ce5 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -100,6 +100,24 @@
 	return ret;
 }
 
+static void msm_buf_mngr_sd_shutdown(struct msm_buf_mngr_device *buf_mngr_dev)
+{
+	unsigned long flags;
+	struct msm_get_bufs *bufs, *save;
+
+	spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
+	if (!list_empty(&buf_mngr_dev->buf_qhead)) {
+		list_for_each_entry_safe(bufs,
+			save, &buf_mngr_dev->buf_qhead, entry) {
+			pr_err("%s: Delete invalid bufs =%x\n", __func__,
+				(unsigned int)bufs);
+			list_del_init(&bufs->entry);
+			kfree(bufs);
+		}
+	}
+	spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
+}
+
 static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
 	unsigned int cmd, void *arg)
 {
@@ -123,6 +141,9 @@
 	case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
 		rc = msm_buf_mngr_put_buf(buf_mngr_dev, argp);
 		break;
+	case MSM_SD_SHUTDOWN:
+		msm_buf_mngr_sd_shutdown(buf_mngr_dev);
+		break;
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 8fa8f8d..0fbaeca 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -251,6 +251,7 @@
 	unsigned long flags;
 	struct msm_vb2_buffer *msm_vb2;
 	struct msm_stream *stream;
+	struct vb2_buffer *vb2_buf = NULL;
 	int rc = 0;
 
 	stream = msm_get_stream(session_id, stream_id);
@@ -258,6 +259,18 @@
 		return 0;
 	spin_lock_irqsave(&stream->stream_lock, flags);
 	if (vb) {
+		list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
+			vb2_buf = &(msm_vb2->vb2_buf);
+			if (vb2_buf == vb)
+				break;
+		}
+		if (vb2_buf != vb) {
+			pr_err("%s:%d VB buffer is INVALID vb=%x, ses_id=%d, str_id=%d\n",
+				__func__, __LINE__, (unsigned int)vb,
+				session_id, stream_id);
+			rc = -EINVAL;
+			goto out;
+		}
 		msm_vb2 =
 			container_of(vb, struct msm_vb2_buffer, vb2_buf);
 		/* put buf before buf done */
@@ -268,10 +281,11 @@
 		} else
 			rc = -EINVAL;
 	} else {
-		pr_err("%s: VB buffer is null\n", __func__);
+		pr_err("%s:%d VB buffer is NULL for ses_id=%d, str_id=%d\n",
+			__func__, __LINE__, session_id, stream_id);
 		rc = -EINVAL;
 	}
-
+out:
 	spin_unlock_irqrestore(&stream->stream_lock, flags);
 	return rc;
 }