[mythtv-users] mythtv/pvr 250: why does it sometimes stop recording?

Jens Axboe mythtv-users at kernel.dk
Thu Oct 23 17:45:13 EDT 2003


On Thu, Oct 23 2003, marduk wrote:
> Thanks for the patch (you guys are cool).  I'll give it a try tonite.

Probably want this one instead, the one attached was an earlier one.
This one closes more holes :)

diff -ur ivtv.vanilla/driver/ivtv-api.c ivtv/driver/ivtv-api.c
--- ivtv.vanilla/driver/ivtv-api.c	2003-10-03 07:02:34.000000000 +0200
+++ ivtv/driver/ivtv-api.c	2003-10-23 16:08:24.000000000 +0200
@@ -1175,7 +1175,7 @@
 		&result, 2, &data[0]);
 	if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 20. Code %d\n",x);
 		
-	if (itv->capturing == 0) {
+	if (atomic_read(&itv->capturing) == 0) {
 	
 		itv->trans_id = 0;
 		itv->first_read = 1;
@@ -1225,7 +1225,7 @@
 	        &result, 2, &data[0]);
 	if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "startcap error 1. Code %d\n",x);
 
-	if (itv->capturing == 0) {
+	if (atomic_read(&itv->capturing) == 0) {
 	        /*Clear the following Interrupt mask bits: 0xd8000000 */
 		itv->irqmask = (itv->irqmask & ~IVTV_IRQ_MASK_CAPTURE);
 	        writel(itv->irqmask,(itv->reg_mem + IVTV_REG_IRQMASK));
@@ -1233,7 +1233,7 @@
 	}
 
 	/*you're live! sit back and await interrupts :)*/
-	itv->capturing++;
+	atomic_inc(&itv->capturing);
 	up(&itv->enc_sem_adm);
 	return 0;
 }
@@ -1283,7 +1283,7 @@
 	IVTV_DEBUG(IVTV_DEBUG_INFO, "Decoder dmaq size %d\n",
 	itv->v4l2.streams[id->type].dma_q.elements);
 	
-	if (itv->decoding == 0)
+	if (atomic_read(&itv->decoding) == 0)
 	{
 	  /* Clear pending interrupts */
 	  IVTV_DEBUG(IVTV_DEBUG_INFO, "Clearing Interrupts\n");
@@ -1355,7 +1356,7 @@
 	             &result, 2, &data[0]);
 	if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN'T START PLAYBACK %d\n",x);
 
-	if (itv->decoding == 0)
+	if (atomic_read(&itv->decoding) == 0)
 	{
 	 /*Clear the following Interrupt mask bits: 0xd8000000 */
 	 itv->irqmask = (itv->irqmask & ~IVTV_IRQ_MASK_DECODE);
@@ -1364,7 +1365,7 @@
 	}
 
 	/*you're live! sit back and await interrupts :)*/
-	itv->decoding++;
+	atomic_inc(&itv->decoding);
 	
 	/* FIXME wrong semaphore still */
 	up(&itv->dec_sem_adm);
@@ -1380,7 +1381,7 @@
 
 	IVTV_DEBUG(IVTV_DEBUG_INFO,"v4l2 unregister\n");
 
-	if (itv->capturing >= 0) ivtv_stop_all_captures(itv);
+	if (atomic_read(&itv->capturing) >= 0) ivtv_stop_all_captures(itv);
 	if (itv->v4l2.tuner.table.tuner) kfree(itv->v4l2.tuner.table.tuner);
 	for (x=0; x < itv->v4l2.streamcount; x++) {
 		/* Catch a possible kernel panic */
@@ -1467,15 +1468,15 @@
 	 
 	IVTV_DEBUG(IVTV_DEBUG_INFO,"v4l2 read\n");
 
+	if (down_interruptible(&id->itv->v4l2.v4l2_lock))
+		return -ERESTARTSYS;
+
 	//FIXME need to handle non-blocking io
 	//FIXME needs locking
 	//FIXME this can be collapsed into 1 var i think
 	if  ((id->itv->v4l2.streams[id->type].capturing == 0) && 
 		     (id->itv->v4l2.streams[id->type].id == -1)) {
 		
-		if (down_interruptible(&id->itv->v4l2.v4l2_lock)) 
-			return -ERESTARTSYS;
-		
 			id->itv->v4l2.streams[id->type].capturing = 1;
 			id->itv->v4l2.streams[id->type].id   	  = id->open_id;
 
@@ -1488,9 +1489,14 @@
 		up(&id->itv->v4l2.v4l2_lock);
 	} else {
 		if (id->open_id != id->itv->v4l2.streams[id->type].id)
-			return -EBUSY;
+			ret = -EBUSY;
 	}
 
+	up(&id->itv->v4l2.v4l2_lock);
+
+	if (ret)
+		return ret;
+
 	if (filp->f_flags & O_NONBLOCK) {
 		if(!(ivtv_stream_has_data(id)) ) 
 			return -EAGAIN;
@@ -1514,21 +1520,27 @@
 		return -EINVAL;
 	}	       
 
+	if (down_interruptible(&id->itv->v4l2.v4l2_lock))
+		return -ERESTARTSYS;
+
 	// Initialize Decoder
 	/* FIXME we'll need to make this its own stream type */
-	/* FIXME semaphore? */
 	if(id->itv->v4l2.streams[id->type].capturing == 0) {
 		id->itv->v4l2.streams[id->type].capturing = 1;
 		id->itv->v4l2.streams[id->type].id = id->open_id;
 		ret = ivtv_start_v4l2_decode(id);
 	} else {
 		if (id->open_id != id->itv->v4l2.streams[id->type].id)
-		return -EBUSY;
+			ret = -EBUSY;
 	}
 
+	up(&id->itv->v4l2.v4l2_lock);
+
+	if (ret)
+		return ret;
+
 	/* do all the work */
-	ret = ivtv_write(id, buf, count);
-  return ret;
+	return ivtv_write(id, buf, count);
 }
 
 int ivtv_v4l2_close(struct inode *inode, struct file *filp) {
@@ -1546,8 +1558,9 @@
 
 		if (down_interruptible(&id->itv->v4l2.v4l2_lock)) 
 			return -ERESTARTSYS;
-			id->itv->v4l2.streams[id->type].capturing = 0;
-			id->itv->v4l2.streams[id->type].id	  = -1;
+
+		id->itv->v4l2.streams[id->type].capturing = 0;
+		id->itv->v4l2.streams[id->type].id	  = -1;
 		up(&id->itv->v4l2.v4l2_lock);
 	}
 	
diff -ur ivtv.vanilla/driver/ivtv-driver.c ivtv/driver/ivtv-driver.c
--- ivtv.vanilla/driver/ivtv-driver.c	2003-10-03 07:17:14.000000000 +0200
+++ ivtv/driver/ivtv-driver.c	2003-10-23 16:30:39.000000000 +0200
@@ -165,21 +165,30 @@
     }
 }
 
-/* Adds buffers to the tail, effectively making a queue */
-int ivtv_enq_buf(struct ivtv_buffer_list *queue, struct ivtv_buffer *buf) {
+int ivtv_get_free_elements(struct ivtv_buffer_list *queue)
+{
 	unsigned long flags;
+	int elements;
 
 	spin_lock_irqsave(&queue->lock, flags);
+	elements = queue->elements;
+	spin_unlock_irqrestore(&queue->lock, flags);
+
+	return elements;
+}
+
+/* Adds buffers to the tail, effectively making a queue */
+int ivtv_enq_buf(struct ivtv_buffer_list *queue, struct ivtv_buffer *buf) {
+	unsigned long flags;
 
 	if (buf == NULL) {
 		IVTV_DEBUG(IVTV_DEBUG_ERR,"EnQ NULL buffer!\n");
-		spin_unlock_irqrestore(&queue->lock, flags);
 		return -EINVAL;
 	}
 
+	spin_lock_irqsave(&queue->lock, flags);
 	list_add_tail(&buf->list, &queue->list);
 	queue->elements++;
-
 	spin_unlock_irqrestore(&queue->lock, flags);
 
 	return 0;
@@ -209,16 +218,13 @@
 }
 
 /* removes buffer from the head */
-struct ivtv_buffer *ivtv_deq_buf(struct ivtv_buffer_list *queue) {
+struct ivtv_buffer *__ivtv_deq_buf(struct ivtv_buffer_list *queue) {
 	struct ivtv_buffer *buf;
-	unsigned long flags;
 
-	spin_lock_irqsave(&queue->lock, flags);
 	/* make sure list has something to DeQ */
 	if (list_empty(&queue->list)) {
 		IVTV_DEBUG(IVTV_DEBUG_INFO,"DeQ from empty list!\n");
 		queue->elements = 0;
-		spin_unlock_irqrestore(&queue->lock, flags);
 		return NULL;
 	}
 
@@ -230,6 +236,15 @@
 	
 	queue->elements--;
 
+	return buf;
+}
+
+struct ivtv_buffer *ivtv_deq_buf(struct ivtv_buffer_list *queue) {
+	struct ivtv_buffer *buf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&queue->lock, flags);
+	buf = __ivtv_deq_buf(queue);
 	spin_unlock_irqrestore(&queue->lock, flags);
 
 	return buf;
@@ -260,6 +275,7 @@
 
 int ivtv_free_queue(struct ivtv_buffer_list *queue) {
         struct ivtv_buffer *item;
+	unsigned long flags;
 	struct ivtv *itv;
 	int x;
 
@@ -268,20 +284,22 @@
 		return -EINVAL;
 	}
 
+	spin_lock_irqsave(&queue->lock, flags);
+
 	/* FIXME ugly */
 	/* verify ivtv before continuing */
 	for (x = 0; x < ivtv_cards_active; x++) {
 		if (queue->vdev->priv == &ivtv_cards[x]) break;
 		if (x == (ivtv_cards_active - 1)) {
 			queue->elements = 0;
-			return 0;
+			goto out;
 		}
 	}
 
 	itv=(struct ivtv *)queue->vdev->priv;
 
 	while (list_empty(&queue->list) == 0) {
-	        item = ivtv_deq_buf(queue);
+	        item = __ivtv_deq_buf(queue);
 		/* FIXME no check to see if it's mapped or not */
 		pci_unmap_single(itv->dev, item->dma_handle,
 					IVTV_DMA_BUF_SIZE, PCI_DMA_TODEVICE);
@@ -294,7 +312,8 @@
 	}
 
 	queue->elements = 0;
-
+out:
+	spin_unlock_irqrestore(&queue->lock, flags);
 	return 0;
 }
 
@@ -335,7 +354,8 @@
 
 int ivtv_move_queue(struct ivtv_buffer_list *src, struct ivtv_buffer_list *dst) {
 	struct ivtv_buffer *buf;
-  while ((buf = ivtv_deq_buf(src))) {
+
+  	while ((buf = ivtv_deq_buf(src))) {
 		ivtv_enq_buf(dst, buf);
 	}
 
@@ -351,15 +371,16 @@
 
         if ( (fd = open(fn, 0, 0)) == -1) {
                 printk(KERN_INFO "Unable to open '%s'.\n", fn);
-                return -EINVAL;
+		l = -EINVAL;
+		goto out;
         }
 	/* the 2 means SEEK_END */
         l = lseek(fd, 0L, 2);
 
         if (l <= 0 || l > IVTV_FIRM_IMAGE_SIZE) {
                 printk(KERN_INFO "Firmware image too large '%s'\n", fn);
-                sys_close(fd);
-                return -ENOMEM;
+		l = -ENOMEM;
+		goto out;
         }
 
 	/* the 2 means SEEK_SET */
@@ -367,10 +388,10 @@
  
         if (read(fd, mem, l) != l){
                 printk(KERN_INFO "Failed to read '%s'.\n", fn);
-                sys_close(fd);
-                return -ENOMEM;
+		l = -ENOMEM;
         }
 
+out:
 	close(fd);
 	set_fs(fs);
 
@@ -410,7 +431,7 @@
 
 	IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping firmware\n");
 
-	if (itv->capturing) {
+	if (atomic_read(&itv->capturing)) {
 		x = ivtv_stop_all_captures(itv);
 		if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 1. Code %d\n",x);
 	}
@@ -430,7 +451,7 @@
 		
 	IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n");
 	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(.01*HZ);
+	schedule_timeout(HZ/100);
 	
 	/*halt dec firmware */
 	if (IVTV_250_V2 != itv->card_type) {
@@ -868,6 +889,8 @@
 	int x;
 	id.itv = itv;
 
+	down(&itv->v4l2.v4l2_lock);
+
 	for (x = 0; x < itv->v4l2.streamcount;x++) {
 		if (itv->v4l2.streams[x].capturing==1) {
 			id.type=x;
@@ -875,6 +898,7 @@
 		}
 	}
 	
+	up(&itv->v4l2.v4l2_lock);
 	return 0;
 }
 
@@ -894,7 +918,7 @@
 	}
 
 	/* only run these if we're shutting down the last cap */
-	if (itv->capturing == 0) {
+	if (atomic_read(&itv->capturing) == 0) {
 		/* event notification (off)*/
 		data[0] = 0; /*type: 0 = refresh */
 		data[1] = 0; /*on/off: 0 = off */
@@ -919,7 +943,7 @@
 		IVTV_DEBUG(IVTV_DEBUG_ERR, "dma still pending! stopping anyway.\n");
 
 	/* only run these if we're shutting down the last cap */
-	if (itv->capturing == 0) {
+	if (atomic_read(&itv->capturing) == 0) {
 		/* wait 1s for EOS interrupt */
 		sleep_on_timeout(&itv->cap_w, 1*HZ);
 
@@ -950,7 +974,7 @@
 	wake_up(&itv->dec_thread_w);
 
 	/* only run these if we're shutting down the last cap */
-	if (itv->decoding == 0) {
+	if (atomic_read(&itv->decoding) == 0) {
 		/* event notification (off)*/
 	        data[0] = 0; /* Event: 0 = audio change between stereo and mono */
 	        data[1] = 0; /* Enable/Disable: 0 = disabled, 1 = enabled */
@@ -976,36 +1000,19 @@
 
 	/* clean up queues */
 	/* move free_q to full_q to clean up partially-filled buffers */
-	while (itv->v4l2.streams[id->type].free_q.elements > 0) {
-		buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].free_q);
-		if (buf == NULL) {
-			IVTV_DEBUG(IVTV_DEBUG_ERR,
-				   "NULL buffer in close_stream (b)\n");
-			break;
-		}
+	while ((buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].free_q))) {
 		buf->buffer.bytesused=0;
 		buf->readpos=0;
 		ivtv_enq_buf(&itv->v4l2.streams[id->type].full_q, buf);
 	}
 
-	while (itv->v4l2.streams[id->type].full_q.elements > 0) {
-		buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].full_q);
-		if (buf == NULL) {
-			IVTV_DEBUG(IVTV_DEBUG_ERR,
-				   "NULL buffer in close_stream (a)\n");
-			break;
-		}
+	while ((buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].full_q))) {
 		buf->buffer.bytesused=0;
 		buf->readpos=0;
 		ivtv_enq_buf(&itv->v4l2.streams[id->type].free_q, buf);
 	}
-	while (itv->v4l2.streams[id->type].dma_q.elements > 0) {
-		buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].dma_q);
-		if (buf == NULL) {
-			IVTV_DEBUG(IVTV_DEBUG_ERR,
-				   "NULL buffer in close_stream (b)\n");
-			break;
-		}
+
+	while ((buf = ivtv_deq_buf(&itv->v4l2.streams[id->type].dma_q))) {
 		buf->buffer.bytesused=0;
 		buf->readpos=0;
 		ivtv_enq_buf(&itv->v4l2.streams[id->type].free_q, buf);
@@ -1029,17 +1036,21 @@
 	/* FIXME mpg only :/ */
 	struct ivtv_v4l2_stream *stream=&itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG];
 	daemonize();
+	exit_files(current);
 	reparent_to_init();
 	strcpy(current->comm, "ivtv-dec");
 
 	IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_thread: pid = %d, itv = 0x%08x\n", 
              current->pid, (u32)itv);
 
+	/* notify initiator that we are up and running */
+	up(&itv->enc_sem_adm);
+
 	while (itv->dec_thread_running) {
 		IVTV_DEBUG(IVTV_DEBUG_INFO, "starting thread %d\n", current->pid);
-		while (itv->decoding) {
+		while (atomic_read(&itv->decoding)) {
 			/* don't want it to get interrupted */
-			sleep_on_timeout(&itv->dec_thread_w, 0.1*HZ);
+			sleep_on_timeout(&itv->dec_thread_w, HZ/10);
 			if (itv->dec_dma_reset == 0) {
 				if (stream->dma_pending == 1) {
 					IVTV_DEBUG(IVTV_DEBUG_ERR,"ivtv_dec_thread: "
@@ -1380,8 +1391,7 @@
 			break;
 	}
 
-	/* FIXME might need locking (unlikely) */
-	free = itv->v4l2.streams[type].free_q.elements;
+	free = ivtv_get_free_elements(&itv->v4l2.streams[type].free_q);
 	/* increment the sequence # */
 	itv->v4l2.streams[type].seq++;
 	
@@ -1390,7 +1400,7 @@
 	if (free <= bufs_needed) {
 		IVTV_DEBUG(IVTV_DEBUG_ERR, "Not enough free buffers, stream %d\n",
 			   type);
-		IVTV_DEBUG(IVTV_DEBUG_INFO, "(fullq: %d, freeq: %d, dmaq: %d)\n",
+		printk(KERN_DEBUG "(fullq: %d, freeq: %d, dmaq: %d)\n",
 			   itv->v4l2.streams[type].full_q.elements,
 			   free,
 			   itv->v4l2.streams[type].dma_q.elements);
@@ -1554,9 +1564,8 @@
 	itv->dec_mbox = NULL;
 	itv->io_mem = NULL;
 	itv->reg_mem = NULL;
-	itv->busy = 0;
-	itv->capturing = 0;
-	itv->decoding  = 0;
+	atomic_set(&itv->capturing, 0);
+	atomic_set(&itv->decoding, 0);
 	itv->dec_dma_pending = 0;
 	itv->user_dma_to_device_state = NULL;
 
@@ -1761,6 +1770,8 @@
 		itv->dec_thread_running = 1;
 		itv->dec_thread_pid = kernel_thread(ivtv_dec_thread, itv,
 						    CLONE_FS | CLONE_FILES);
+		/* wait for thread to finish starting */
+		down(&itv->enc_sem_adm);
 	}
 	
 	return 0;
@@ -1801,7 +1812,7 @@
 	writel(itv->irqmask, (itv->reg_mem + IVTV_REG_IRQMASK));
 
 	IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping thread\n");
-	itv->decoding = 0;
+	atomic_set(&itv->decoding, 0);
 	itv->dec_thread_running = 0;
 	wake_up(&itv->dec_thread_w);
 	
@@ -1956,15 +1967,10 @@
 
 	IVTV_DEBUG(IVTV_DEBUG_INFO, " Read stream.. \n");
 
-	if(down_interruptible(&itv->enc_sem_adm)) return -ERESTARTSYS;
-
-	if (0 == itv->capturing) {
-		up(&itv->enc_sem_adm);
+	if (atomic_read(&itv->capturing) == 0) {
 		IVTV_DEBUG(IVTV_DEBUG_ERR,
 			   "Stream not initialized before read(shouldn't happen)\n");
 		return -EIO;
-	} else {
-	       	up(&itv->enc_sem_adm);
 	}
 
 	sleepctr = 0;
@@ -1972,7 +1978,7 @@
 	/* FIXME find a way to gracefully exit capture */
 
 	/* FIXME need spinlock here*/
-	while (st->full_q.elements == 0) {
+	while (ivtv_get_free_elements(&st->full_q) == 0) {
 
 		sleepctr++;
 		sleep_on_timeout(&st->waitq, IVTV_SLEEP_WAIT);
@@ -2055,14 +2061,9 @@
 			buf = ivtv_deq_buf(&st->full_q);
 			ivtv_enq_buf(&st->free_q, buf);
 		
-			if (st->full_q.elements != 0) {
+			buf = ivtv_deq_peek_head(&st->full_q);
+			if (buf) {
 				tid = buf->buffer.sequence;
-				buf = ivtv_deq_peek_head(&st->full_q);
-				if (buf == NULL) {
-					IVTV_DEBUG(IVTV_DEBUG_ERR,
-					"Error obtaining buffer(shouldnt happen)\n");
-					break;
-				}
 				if (buf->buffer.sequence != tid) {
 					/* end of frame! */
 					st->ubytes = 0;
@@ -2549,13 +2550,11 @@
 }
 
 int ivtv_stream_has_data(struct ivtv_open_id *id) {
-	if(id->itv->v4l2.streams[id->type].full_q.elements != 0) return 1;
-	return 0;
+	return ivtv_get_free_elements(&id->itv->v4l2.streams[id->type].full_q);
 }
 
 int ivtv_dec_stream_has_space(struct ivtv_open_id *id) {
-	if(id->itv->v4l2.streams[id->type].free_q.elements != 0) return 1;
-	return 0;
+	return ivtv_get_free_elements(&id->itv->v4l2.streams[id->type].free_q);
 }
 
 unsigned int ivtv_dec_poll(struct file *filp, poll_table *wait) {
@@ -2565,6 +2564,9 @@
 	/* add stream's waitq to the poll list */
 	poll_wait(filp, &id->itv->v4l2.streams[id->type].waitq, wait);
 
+	if (down_interruptible(&id->itv->v4l2.v4l2_lock))
+		return -ERESTARTSYS;
+
 	if(ivtv_dec_stream_has_space(id)) {
 		mask |= POLLIN | POLLRDNORM; /* readable */
 	}
@@ -2574,6 +2576,7 @@
 		mask = POLLERR;
 	}
 
+	up(&id->itv->v4l2.v4l2_lock);
 	return mask;
 }
 
@@ -2584,6 +2587,9 @@
 	/* add stream's waitq to the poll list */
 	poll_wait(filp, &id->itv->v4l2.streams[id->type].waitq, wait);
 
+	if (down_interruptible(&id->itv->v4l2.v4l2_lock))
+		return -ERESTARTSYS;
+
 	if(ivtv_stream_has_data(id)) {
 		mask |= POLLIN | POLLRDNORM; /* readable */
 	}
@@ -2593,6 +2599,7 @@
 		mask = POLLERR;
 	}
 
+	up(&id->itv->v4l2.v4l2_lock);
 	return mask;
 }
 
@@ -2651,40 +2658,21 @@
 
 int ivtv_close(struct ivtv_open_id *id) {
 	struct ivtv *itv=id->itv;
-	int capflag=0, decflag=0, x;
 
-	down(&itv->enc_sem_adm);
-		if (itv->capturing) {
-			capflag =1;
-		}
-	up(&itv->enc_sem_adm);
-	
-	/* FIXME needs semaphore */
-		if(itv->decoding) {
-			decflag=1;
-		}
-	/* end sem */
-	if(capflag) {
-		if( (id->type != IVTV_DEC_STREAM_TYPE_MPG) &&
-                    (id->type != IVTV_DEC_STREAM_TYPE_YUV)) {
-			down(&itv->enc_sem_adm);
-				itv->capturing--;
-			up(&itv->enc_sem_adm);
-			x = ivtv_stop_capture(id);
-			return x;
+	if( (id->type != IVTV_DEC_STREAM_TYPE_MPG) && (id->type != IVTV_DEC_STREAM_TYPE_YUV)) {
+		if (atomic_read(&itv->capturing)) {
+			atomic_dec(&itv->capturing);
+			return ivtv_stop_capture(id);
 		}
 	}
 
-	if(decflag) {
-		if( (id->type == IVTV_DEC_STREAM_TYPE_MPG) ||
-                    (id->type == IVTV_DEC_STREAM_TYPE_YUV)) {
-			/* FIXME needs semaphore */
-				itv->decoding--;
-			/* end sem */
-			x = ivtv_stop_decode(id);	
-			return x;
+	if( (id->type == IVTV_DEC_STREAM_TYPE_MPG) || (id->type == IVTV_DEC_STREAM_TYPE_YUV)) {
+		if (atomic_read(&itv->decoding)) {
+			atomic_dec(&itv->decoding);
+			return ivtv_stop_decode(id);
 		}
 	}
+
 	return 0;
 }
 
diff -ur ivtv.vanilla/driver/ivtv.h ivtv/driver/ivtv.h
--- ivtv.vanilla/driver/ivtv.h	2003-10-03 09:07:33.000000000 +0200
+++ ivtv/driver/ivtv.h	2003-10-23 15:50:51.000000000 +0200
@@ -632,8 +632,8 @@
 	int num;                /* invalidate during init! */
 	int first_read;		/* used to clean up stream */
 	int first_write;	/* don't schedule decodes until buffers full */
-	int busy, capturing;	/* FIXME obseleted by v4l2|consolidate into flags? */
-	int decoding;
+	atomic_t capturing;
+	atomic_t decoding;
 	struct semaphore enc_sem_r, enc_sem_w, enc_sem_adm;
 	struct semaphore dec_sem_r, dec_sem_w, dec_sem_adm;
 	struct semaphore dec_sched_dma_sem;

-- 
Jens Axboe



More information about the mythtv-users mailing list