Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cdc03781 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

[media] ivtv: switch to the v4l core lock

parent 4d68e700
Loading
Loading
Loading
Loading
+14 −34
Original line number Diff line number Diff line
@@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
		}

		/* wait for more data to arrive */
		mutex_unlock(&itv->serialize_lock);
		prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
		/* New buffers might have become available before we were added to the waitqueue */
		if (!s->q_full.buffers)
			schedule();
		finish_wait(&s->waitq, &wait);
		mutex_lock(&itv->serialize_lock);
		if (signal_pending(current)) {
			/* return if a signal was received */
			IVTV_DEBUG_INFO("User stopped %s\n", s->name);
@@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_

	IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);

	mutex_lock(&itv->serialize_lock);
	rc = ivtv_start_capture(id);
	mutex_unlock(&itv->serialize_lock);
	if (rc)
		return rc;
	return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
@@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
	set_bit(IVTV_F_S_APPL_IO, &s->s_flags);

	/* Start decoder (returns 0 if already started) */
	mutex_lock(&itv->serialize_lock);
	rc = ivtv_start_decoding(id, itv->speed);
	mutex_unlock(&itv->serialize_lock);
	if (rc) {
		IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);

@@ -627,11 +625,13 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
			break;
		if (filp->f_flags & O_NONBLOCK)
			return -EAGAIN;
		mutex_unlock(&itv->serialize_lock);
		prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
		/* New buffers might have become free before we were added to the waitqueue */
		if (!s->q_free.buffers)
			schedule();
		finish_wait(&s->waitq, &wait);
		mutex_lock(&itv->serialize_lock);
		if (signal_pending(current)) {
			IVTV_DEBUG_INFO("User stopped %s\n", s->name);
			return -EINTR;
@@ -686,12 +686,14 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
			if (mode == OUT_YUV)
				ivtv_yuv_setup_stream_frame(itv);

			mutex_unlock(&itv->serialize_lock);
			prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
			while (!(got_sig = signal_pending(current)) &&
					test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
				schedule();
			}
			finish_wait(&itv->dma_waitq, &wait);
			mutex_lock(&itv->serialize_lock);
			if (got_sig) {
				IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
				return -EINTR;
@@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
	if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
		int rc;

		mutex_lock(&itv->serialize_lock);
		rc = ivtv_start_capture(id);
		mutex_unlock(&itv->serialize_lock);
		if (rc) {
			IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
					s->name, rc);
@@ -861,7 +861,6 @@ int ivtv_v4l2_close(struct file *filp)

	IVTV_DEBUG_FILE("close %s\n", s->name);

	mutex_lock(&itv->serialize_lock);
	/* Stop radio */
	if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
			v4l2_fh_is_singular_file(filp)) {
@@ -893,7 +892,6 @@ int ivtv_v4l2_close(struct file *filp)
	/* Easy case first: this stream was never claimed by us */
	if (s->id != id->open_id) {
		kfree(id);
		mutex_unlock(&itv->serialize_lock);
		return 0;
	}

@@ -914,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp)
		ivtv_stop_capture(id, 0);
	}
	kfree(id);
	mutex_unlock(&itv->serialize_lock);
	return 0;
}

static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
int ivtv_v4l2_open(struct file *filp)
{
#ifdef CONFIG_VIDEO_ADV_DEBUG
	struct video_device *vdev = video_devdata(filp);
#endif
	struct ivtv_stream *s = video_get_drvdata(vdev);
	struct ivtv *itv = s->itv;
	struct ivtv_open_id *item;
	int res = 0;

	IVTV_DEBUG_FILE("open %s\n", s->name);

	if (ivtv_init_on_first_open(itv)) {
		IVTV_ERR("Failed to initialize on device %s\n",
			 video_device_node_name(vdev));
		return -ENXIO;
	}

#ifdef CONFIG_VIDEO_ADV_DEBUG
	/* Unless ivtv_fw_debug is set, error out if firmware dead. */
	if (ivtv_fw_debug) {
@@ -1017,28 +1019,6 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
	return 0;
}

int ivtv_v4l2_open(struct file *filp)
{
	int res;
	struct ivtv *itv = NULL;
	struct ivtv_stream *s = NULL;
	struct video_device *vdev = video_devdata(filp);

	s = video_get_drvdata(vdev);
	itv = s->itv;

	mutex_lock(&itv->serialize_lock);
	if (ivtv_init_on_first_open(itv)) {
		IVTV_ERR("Failed to initialize on device %s\n",
			 video_device_node_name(vdev));
		mutex_unlock(&itv->serialize_lock);
		return -ENXIO;
	}
	res = ivtv_serialized_open(s, filp);
	mutex_unlock(&itv->serialize_lock);
	return res;
}

void ivtv_mute(struct ivtv *itv)
{
	if (atomic_read(&itv->capturing))
+5 −17
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
		ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);

		/* Wait for any DMA to finish */
		mutex_unlock(&itv->serialize_lock);
		prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
		while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
			got_sig = signal_pending(current);
@@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
			schedule();
		}
		finish_wait(&itv->dma_waitq, &wait);
		mutex_lock(&itv->serialize_lock);
		if (got_sig)
			return -EINTR;

@@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
	 * happens within the first 100 lines of the top field.
	 * Make 4 attempts to sync to the decoder before giving up.
	 */
	mutex_unlock(&itv->serialize_lock);
	for (f = 0; f < 4; f++) {
		prepare_to_wait(&itv->vsync_waitq, &wait,
				TASK_UNINTERRUPTIBLE);
@@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
		schedule_timeout(msecs_to_jiffies(25));
	}
	finish_wait(&itv->vsync_waitq, &wait);
	mutex_lock(&itv->serialize_lock);

	if (f == 4)
		IVTV_WARN("Mode change failed to sync to decoder\n");
@@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio,
	return 0;
}

static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
		unsigned int cmd, unsigned long arg)
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	struct video_device *vfd = video_devdata(filp);
	long ret;
@@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
	return ret;
}

long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	struct ivtv_open_id *id = fh2id(filp->private_data);
	struct ivtv *itv = id->itv;
	long res;

	/* DQEVENT can block, so this should not run with the serialize lock */
	if (cmd == VIDIOC_DQEVENT)
		return ivtv_serialized_ioctl(itv, filp, cmd, arg);
	mutex_lock(&itv->serialize_lock);
	res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
	mutex_unlock(&itv->serialize_lock);
	return res;
}

static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
	.vidioc_querycap    		    = ivtv_querycap,
	.vidioc_s_audio     		    = ivtv_s_audio,
+1 −0
Original line number Diff line number Diff line
@@ -214,6 +214,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
	s->vdev->fops = ivtv_stream_info[type].fops;
	s->vdev->release = video_device_release;
	s->vdev->tvnorms = V4L2_STD_ALL;
	s->vdev->lock = &itv->serialize_lock;
	set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
	ivtv_set_funcs(s->vdev);
	return 0;
+19 −3
Original line number Diff line number Diff line
@@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
{
	struct yuv_playback_info *yi = &itv->yuv_info;
	struct ivtv_dma_frame dma_args;
	int res;

	ivtv_yuv_setup_stream_frame(itv);

	/* We only need to supply source addresses for this */
	dma_args.y_source = src;
	dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
	return ivtv_yuv_udma_frame(itv, &dma_args);
	/* Wait for frame DMA. Note that serialize_lock is locked,
	   so to allow other processes to access the driver while
	   we are waiting unlock first and later lock again. */
	mutex_unlock(&itv->serialize_lock);
	res = ivtv_yuv_udma_frame(itv, &dma_args);
	mutex_lock(&itv->serialize_lock);
	return res;
}

/* IVTV_IOC_DMA_FRAME ioctl handler */
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
{
/*	IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
	int res;

/*	IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
	ivtv_yuv_next_free(itv);
	ivtv_yuv_setup_frame(itv, args);
	return ivtv_yuv_udma_frame(itv, args);
	/* Wait for frame DMA. Note that serialize_lock is locked,
	   so to allow other processes to access the driver while
	   we are waiting unlock first and later lock again. */
	mutex_unlock(&itv->serialize_lock);
	res = ivtv_yuv_udma_frame(itv, args);
	mutex_lock(&itv->serialize_lock);
	return res;
}

void ivtv_yuv_close(struct ivtv *itv)
@@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv)
	int h_filter, v_filter_1, v_filter_2;

	IVTV_DEBUG_YUV("ivtv_yuv_close\n");
	mutex_unlock(&itv->serialize_lock);
	ivtv_waitq(&itv->vsync_waitq);
	mutex_lock(&itv->serialize_lock);

	yi->running = 0;
	atomic_set(&yi->next_dma_frame, -1);