Merge "msm: camera: Fix Use after free bug in msm_vb2.c"
This commit is contained in:
commit
b878a7b799
4 changed files with 210 additions and 27 deletions
|
@ -283,22 +283,47 @@ void msm_delete_stream(unsigned int session_id, unsigned int stream_id)
|
||||||
struct msm_session *session = NULL;
|
struct msm_session *session = NULL;
|
||||||
struct msm_stream *stream = NULL;
|
struct msm_stream *stream = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int try_count = 0;
|
||||||
|
|
||||||
session = msm_queue_find(msm_session_q, struct msm_session,
|
session = msm_queue_find(msm_session_q, struct msm_session,
|
||||||
list, __msm_queue_find_session, &session_id);
|
list, __msm_queue_find_session, &session_id);
|
||||||
|
|
||||||
if (!session)
|
if (!session)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stream = msm_queue_find(&session->stream_q, struct msm_stream,
|
while (1) {
|
||||||
list, __msm_queue_find_stream, &stream_id);
|
|
||||||
if (!stream)
|
if (try_count > 5) {
|
||||||
return;
|
pr_err("%s : not able to delete stream %d\n",
|
||||||
spin_lock_irqsave(&(session->stream_q.lock), flags);
|
__func__, __LINE__);
|
||||||
list_del_init(&stream->list);
|
break;
|
||||||
session->stream_q.len--;
|
}
|
||||||
kfree(stream);
|
|
||||||
stream = NULL;
|
write_lock(&session->stream_rwlock);
|
||||||
spin_unlock_irqrestore(&(session->stream_q.lock), flags);
|
try_count++;
|
||||||
|
stream = msm_queue_find(&session->stream_q, struct msm_stream,
|
||||||
|
list, __msm_queue_find_stream, &stream_id);
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
write_unlock(&session->stream_rwlock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msm_vb2_get_stream_state(stream) != 1) {
|
||||||
|
write_unlock(&session->stream_rwlock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&(session->stream_q.lock), flags);
|
||||||
|
list_del_init(&stream->list);
|
||||||
|
session->stream_q.len--;
|
||||||
|
kfree(stream);
|
||||||
|
stream = NULL;
|
||||||
|
spin_unlock_irqrestore(&(session->stream_q.lock), flags);
|
||||||
|
write_unlock(&session->stream_rwlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_delete_stream);
|
EXPORT_SYMBOL(msm_delete_stream);
|
||||||
|
|
||||||
|
@ -446,6 +471,7 @@ int msm_create_session(unsigned int session_id, struct video_device *vdev)
|
||||||
mutex_init(&session->lock);
|
mutex_init(&session->lock);
|
||||||
mutex_init(&session->lock_q);
|
mutex_init(&session->lock_q);
|
||||||
mutex_init(&session->close_lock);
|
mutex_init(&session->close_lock);
|
||||||
|
rwlock_init(&session->stream_rwlock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_create_session);
|
EXPORT_SYMBOL(msm_create_session);
|
||||||
|
@ -1040,17 +1066,25 @@ static struct v4l2_file_operations msm_fops = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_stream *msm_get_stream(unsigned int session_id,
|
struct msm_session *msm_get_session(unsigned int session_id)
|
||||||
unsigned int stream_id)
|
|
||||||
{
|
{
|
||||||
struct msm_session *session;
|
struct msm_session *session;
|
||||||
struct msm_stream *stream;
|
|
||||||
|
|
||||||
session = msm_queue_find(msm_session_q, struct msm_session,
|
session = msm_queue_find(msm_session_q, struct msm_session,
|
||||||
list, __msm_queue_find_session, &session_id);
|
list, __msm_queue_find_session, &session_id);
|
||||||
if (!session)
|
if (!session)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_get_session);
|
||||||
|
|
||||||
|
|
||||||
|
struct msm_stream *msm_get_stream(struct msm_session *session,
|
||||||
|
unsigned int stream_id)
|
||||||
|
{
|
||||||
|
struct msm_stream *stream;
|
||||||
|
|
||||||
stream = msm_queue_find(&session->stream_q, struct msm_stream,
|
stream = msm_queue_find(&session->stream_q, struct msm_stream,
|
||||||
list, __msm_queue_find_stream, &stream_id);
|
list, __msm_queue_find_stream, &stream_id);
|
||||||
|
|
||||||
|
@ -1108,6 +1142,34 @@ struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_get_stream_from_vb2q);
|
EXPORT_SYMBOL(msm_get_stream_from_vb2q);
|
||||||
|
|
||||||
|
struct msm_session *msm_get_session_from_vb2q(struct vb2_queue *q)
|
||||||
|
{
|
||||||
|
struct msm_session *session;
|
||||||
|
struct msm_stream *stream;
|
||||||
|
unsigned long flags1;
|
||||||
|
unsigned long flags2;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&msm_session_q->lock, flags1);
|
||||||
|
list_for_each_entry(session, &(msm_session_q->list), list) {
|
||||||
|
spin_lock_irqsave(&(session->stream_q.lock), flags2);
|
||||||
|
list_for_each_entry(
|
||||||
|
stream, &(session->stream_q.list), list) {
|
||||||
|
if (stream->vb2_q == q) {
|
||||||
|
spin_unlock_irqrestore
|
||||||
|
(&(session->stream_q.lock), flags2);
|
||||||
|
spin_unlock_irqrestore
|
||||||
|
(&msm_session_q->lock, flags1);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&(session->stream_q.lock), flags2);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&msm_session_q->lock, flags1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_get_session_from_vb2q);
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
long msm_copy_camera_private_ioctl_args(unsigned long arg,
|
long msm_copy_camera_private_ioctl_args(unsigned long arg,
|
||||||
struct msm_camera_private_ioctl_arg *k_ioctl,
|
struct msm_camera_private_ioctl_arg *k_ioctl,
|
||||||
|
|
|
@ -114,6 +114,7 @@ struct msm_session {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct mutex lock_q;
|
struct mutex lock_q;
|
||||||
struct mutex close_lock;
|
struct mutex close_lock;
|
||||||
|
rwlock_t stream_rwlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool msm_is_daemon_present(void)
|
static inline bool msm_is_daemon_present(void)
|
||||||
|
@ -131,11 +132,13 @@ int msm_create_stream(unsigned int session_id,
|
||||||
void msm_delete_stream(unsigned int session_id, unsigned int stream_id);
|
void msm_delete_stream(unsigned int session_id, unsigned int stream_id);
|
||||||
int msm_create_command_ack_q(unsigned int session_id, unsigned int stream_id);
|
int msm_create_command_ack_q(unsigned int session_id, unsigned int stream_id);
|
||||||
void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id);
|
void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id);
|
||||||
struct msm_stream *msm_get_stream(unsigned int session_id,
|
struct msm_session *msm_get_session(unsigned int session_id);
|
||||||
|
struct msm_stream *msm_get_stream(struct msm_session *session,
|
||||||
unsigned int stream_id);
|
unsigned int stream_id);
|
||||||
struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
|
struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
|
||||||
unsigned int stream_id);
|
unsigned int stream_id);
|
||||||
struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q);
|
struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q);
|
||||||
|
struct msm_session *msm_get_session_from_vb2q(struct vb2_queue *q);
|
||||||
struct msm_session *msm_session_find(unsigned int session_id);
|
struct msm_session *msm_session_find(unsigned int session_id);
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
long msm_copy_camera_private_ioctl_args(unsigned long arg,
|
long msm_copy_camera_private_ioctl_args(unsigned long arg,
|
||||||
|
|
|
@ -44,17 +44,25 @@ static int msm_vb2_queue_setup(struct vb2_queue *q,
|
||||||
static int msm_vb2_buf_init(struct vb2_buffer *vb)
|
static int msm_vb2_buf_init(struct vb2_buffer *vb)
|
||||||
{
|
{
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
|
struct msm_session *session;
|
||||||
struct msm_vb2_buffer *msm_vb2_buf;
|
struct msm_vb2_buffer *msm_vb2_buf;
|
||||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||||
|
|
||||||
|
session = msm_get_session_from_vb2q(vb->vb2_queue);
|
||||||
|
if (IS_ERR_OR_NULL(session))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
pr_err("%s: Couldn't find stream\n", __func__);
|
pr_err("%s: Couldn't find stream\n", __func__);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
msm_vb2_buf = container_of(vbuf, struct msm_vb2_buffer, vb2_v4l2_buf);
|
msm_vb2_buf = container_of(vbuf, struct msm_vb2_buffer, vb2_v4l2_buf);
|
||||||
msm_vb2_buf->in_freeq = 0;
|
msm_vb2_buf->in_freeq = 0;
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +70,7 @@ static void msm_vb2_buf_queue(struct vb2_buffer *vb)
|
||||||
{
|
{
|
||||||
struct msm_vb2_buffer *msm_vb2;
|
struct msm_vb2_buffer *msm_vb2;
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
|
struct msm_session *session;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||||
|
|
||||||
|
@ -71,21 +80,30 @@ static void msm_vb2_buf_queue(struct vb2_buffer *vb)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session = msm_get_session_from_vb2q(vb->vb2_queue);
|
||||||
|
if (IS_ERR_OR_NULL(session))
|
||||||
|
return;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
pr_err("%s:%d] NULL stream", __func__, __LINE__);
|
pr_err("%s:%d] NULL stream", __func__, __LINE__);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&stream->stream_lock, flags);
|
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||||
list_add_tail(&msm_vb2->list, &stream->queued_list);
|
list_add_tail(&msm_vb2->list, &stream->queued_list);
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msm_vb2_buf_finish(struct vb2_buffer *vb)
|
static void msm_vb2_buf_finish(struct vb2_buffer *vb)
|
||||||
{
|
{
|
||||||
struct msm_vb2_buffer *msm_vb2;
|
struct msm_vb2_buffer *msm_vb2;
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
|
struct msm_session *session;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct msm_vb2_buffer *msm_vb2_entry, *temp;
|
struct msm_vb2_buffer *msm_vb2_entry, *temp;
|
||||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||||
|
@ -96,9 +114,16 @@ static void msm_vb2_buf_finish(struct vb2_buffer *vb)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session = msm_get_session_from_vb2q(vb->vb2_queue);
|
||||||
|
if (IS_ERR_OR_NULL(session))
|
||||||
|
return;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
pr_err("%s:%d] NULL stream", __func__, __LINE__);
|
pr_err("%s:%d] NULL stream", __func__, __LINE__);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,18 +136,27 @@ static void msm_vb2_buf_finish(struct vb2_buffer *vb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msm_vb2_stop_stream(struct vb2_queue *q)
|
static void msm_vb2_stop_stream(struct vb2_queue *q)
|
||||||
{
|
{
|
||||||
struct msm_vb2_buffer *msm_vb2, *temp;
|
struct msm_vb2_buffer *msm_vb2, *temp;
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
|
struct msm_session *session;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct vb2_v4l2_buffer *vb2_v4l2_buf;
|
struct vb2_v4l2_buffer *vb2_v4l2_buf;
|
||||||
|
|
||||||
|
session = msm_get_session_from_vb2q(q);
|
||||||
|
if (IS_ERR_OR_NULL(session))
|
||||||
|
return;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
stream = msm_get_stream_from_vb2q(q);
|
stream = msm_get_stream_from_vb2q(q);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
pr_err_ratelimited("%s:%d] NULL stream", __func__, __LINE__);
|
pr_err_ratelimited("%s:%d] NULL stream", __func__, __LINE__);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +176,28 @@ static void msm_vb2_stop_stream(struct vb2_queue *q)
|
||||||
msm_vb2->in_freeq = 0;
|
msm_vb2->in_freeq = 0;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int msm_vb2_get_stream_state(struct msm_stream *stream)
|
||||||
|
{
|
||||||
|
struct msm_vb2_buffer *msm_vb2, *temp;
|
||||||
|
unsigned long flags;
|
||||||
|
int rc = 1;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||||
|
list_for_each_entry_safe(msm_vb2, temp, &(stream->queued_list), list) {
|
||||||
|
if (msm_vb2->in_freeq != 0) {
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_vb2_get_stream_state);
|
||||||
|
|
||||||
|
|
||||||
static struct vb2_ops msm_vb2_get_q_op = {
|
static struct vb2_ops msm_vb2_get_q_op = {
|
||||||
.queue_setup = msm_vb2_queue_setup,
|
.queue_setup = msm_vb2_queue_setup,
|
||||||
.buf_init = msm_vb2_buf_init,
|
.buf_init = msm_vb2_buf_init,
|
||||||
|
@ -199,13 +253,22 @@ static struct vb2_v4l2_buffer *msm_vb2_get_buf(int session_id,
|
||||||
{
|
{
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
||||||
|
struct msm_session *session;
|
||||||
struct msm_vb2_buffer *msm_vb2 = NULL;
|
struct msm_vb2_buffer *msm_vb2 = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
stream = msm_get_stream(session_id, stream_id);
|
session = msm_get_session(session_id);
|
||||||
if (IS_ERR_OR_NULL(stream))
|
if (IS_ERR_OR_NULL(session))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
|
stream = msm_get_stream(session, stream_id);
|
||||||
|
if (IS_ERR_OR_NULL(stream)) {
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&stream->stream_lock, flags);
|
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||||
|
|
||||||
if (!stream->vb2_q) {
|
if (!stream->vb2_q) {
|
||||||
|
@ -228,6 +291,7 @@ static struct vb2_v4l2_buffer *msm_vb2_get_buf(int session_id,
|
||||||
vb2_v4l2_buf = NULL;
|
vb2_v4l2_buf = NULL;
|
||||||
end:
|
end:
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return vb2_v4l2_buf;
|
return vb2_v4l2_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,13 +300,23 @@ static struct vb2_v4l2_buffer *msm_vb2_get_buf_by_idx(int session_id,
|
||||||
{
|
{
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
||||||
|
struct msm_session *session;
|
||||||
struct msm_vb2_buffer *msm_vb2 = NULL;
|
struct msm_vb2_buffer *msm_vb2 = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
stream = msm_get_stream(session_id, stream_id);
|
session = msm_get_session(session_id);
|
||||||
if (IS_ERR_OR_NULL(stream))
|
if (IS_ERR_OR_NULL(session))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
|
stream = msm_get_stream(session, stream_id);
|
||||||
|
|
||||||
|
if (IS_ERR_OR_NULL(stream)) {
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&stream->stream_lock, flags);
|
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||||
|
|
||||||
if (!stream->vb2_q) {
|
if (!stream->vb2_q) {
|
||||||
|
@ -263,6 +337,7 @@ static struct vb2_v4l2_buffer *msm_vb2_get_buf_by_idx(int session_id,
|
||||||
vb2_v4l2_buf = NULL;
|
vb2_v4l2_buf = NULL;
|
||||||
end:
|
end:
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return vb2_v4l2_buf;
|
return vb2_v4l2_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,15 +345,24 @@ static int msm_vb2_put_buf(struct vb2_v4l2_buffer *vb, int session_id,
|
||||||
unsigned int stream_id)
|
unsigned int stream_id)
|
||||||
{
|
{
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
|
struct msm_session *session;
|
||||||
struct msm_vb2_buffer *msm_vb2;
|
struct msm_vb2_buffer *msm_vb2;
|
||||||
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
stream = msm_get_stream(session_id, stream_id);
|
session = msm_get_session(session_id);
|
||||||
if (IS_ERR_OR_NULL(stream))
|
if (IS_ERR_OR_NULL(session))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
|
stream = msm_get_stream(session, stream_id);
|
||||||
|
if (IS_ERR_OR_NULL(stream)) {
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&stream->stream_lock, flags);
|
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||||
if (vb) {
|
if (vb) {
|
||||||
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
|
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
|
||||||
|
@ -306,6 +390,7 @@ static int msm_vb2_put_buf(struct vb2_v4l2_buffer *vb, int session_id,
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,11 +402,21 @@ static int msm_vb2_buf_done(struct vb2_v4l2_buffer *vb, int session_id,
|
||||||
struct msm_vb2_buffer *msm_vb2;
|
struct msm_vb2_buffer *msm_vb2;
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
||||||
|
struct msm_session *session;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
stream = msm_get_stream(session_id, stream_id);
|
session = msm_get_session(session_id);
|
||||||
if (IS_ERR_OR_NULL(stream))
|
if (IS_ERR_OR_NULL(session))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
|
stream = msm_get_stream(session, stream_id);
|
||||||
|
if (IS_ERR_OR_NULL(stream)) {
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&stream->stream_lock, flags);
|
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||||
if (vb) {
|
if (vb) {
|
||||||
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
|
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
|
||||||
|
@ -353,6 +448,7 @@ static int msm_vb2_buf_done(struct vb2_v4l2_buffer *vb, int session_id,
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,14 +457,23 @@ long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
|
||||||
{
|
{
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
||||||
|
struct msm_session *session;
|
||||||
struct msm_vb2_buffer *msm_vb2 = NULL;
|
struct msm_vb2_buffer *msm_vb2 = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
long rc = -EINVAL;
|
long rc = -EINVAL;
|
||||||
|
|
||||||
stream = msm_get_stream(session_id, stream_id);
|
session = msm_get_session(session_id);
|
||||||
if (IS_ERR_OR_NULL(stream))
|
if (IS_ERR_OR_NULL(session))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
|
stream = msm_get_stream(session, stream_id);
|
||||||
|
if (IS_ERR_OR_NULL(stream)) {
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&stream->stream_lock, flags);
|
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||||
|
|
||||||
if (!stream->vb2_q) {
|
if (!stream->vb2_q) {
|
||||||
|
@ -394,6 +499,7 @@ long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
|
||||||
|
|
||||||
end:
|
end:
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_vb2_return_buf_by_idx);
|
EXPORT_SYMBOL(msm_vb2_return_buf_by_idx);
|
||||||
|
@ -404,10 +510,20 @@ static int msm_vb2_flush_buf(int session_id, unsigned int stream_id)
|
||||||
struct msm_vb2_buffer *msm_vb2;
|
struct msm_vb2_buffer *msm_vb2;
|
||||||
struct msm_stream *stream;
|
struct msm_stream *stream;
|
||||||
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
|
||||||
|
struct msm_session *session;
|
||||||
|
|
||||||
stream = msm_get_stream(session_id, stream_id);
|
session = msm_get_session(session_id);
|
||||||
if (IS_ERR_OR_NULL(stream))
|
if (IS_ERR_OR_NULL(session))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
read_lock(&session->stream_rwlock);
|
||||||
|
|
||||||
|
stream = msm_get_stream(session, stream_id);
|
||||||
|
if (IS_ERR_OR_NULL(stream)) {
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&stream->stream_lock, flags);
|
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||||
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
|
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
|
||||||
vb2_v4l2_buf = &(msm_vb2->vb2_v4l2_buf);
|
vb2_v4l2_buf = &(msm_vb2->vb2_v4l2_buf);
|
||||||
|
@ -416,6 +532,7 @@ static int msm_vb2_flush_buf(int session_id, unsigned int stream_id)
|
||||||
msm_vb2->in_freeq = 0;
|
msm_vb2->in_freeq = 0;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||||
|
read_unlock(&session->stream_rwlock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,5 +68,6 @@ struct vb2_mem_ops *msm_vb2_get_q_mem_ops(void);
|
||||||
int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req_sd);
|
int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req_sd);
|
||||||
long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
|
long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
|
||||||
uint32_t index);
|
uint32_t index);
|
||||||
|
int msm_vb2_get_stream_state(struct msm_stream *stream);
|
||||||
|
|
||||||
#endif /*_MSM_VB_H */
|
#endif /*_MSM_VB_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue