struct list_head vivi_devlist;
struct mutex lock;
+ spinlock_t slock;
int users;
struct vivi_dmaqueue vidq;
/* Several counters */
- int h, m, s, us, jiffies;
+ int h, m, s, ms;
+ unsigned long jiffies;
char timestr[13];
int mv_count; /* Controls bars movement */
/* Updates stream time */
- dev->us += jiffies_to_usecs(jiffies-dev->jiffies);
+ dev->ms += jiffies_to_msecs(jiffies-dev->jiffies);
dev->jiffies = jiffies;
- if (dev->us >= 1000000) {
- dev->us -= 1000000;
+ if (dev->ms >= 1000) {
+ dev->ms -= 1000;
dev->s++;
if (dev->s >= 60) {
dev->s -= 60;
}
}
sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
- dev->h, dev->m, dev->s, (dev->us + 500) / 1000);
+ dev->h, dev->m, dev->s, dev->ms);
dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n",
dev->timestr, (unsigned long)tmpbuf, pos);
int bc;
+ spin_lock(&dev->slock);
/* Announces videobuf that all went ok */
for (bc = 0;; bc++) {
if (list_empty(&dma_q->active)) {
/* Nobody is waiting something to be done, just return */
if (!waitqueue_active(&buf->vb.done)) {
mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+ spin_unlock(&dev->slock);
return;
}
if (bc != 1)
dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n",
__FUNCTION__, bc);
+ spin_unlock(&dev->slock);
}
+#define frames_to_ms(frames) \
+ ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
+
static void vivi_sleep(struct vivi_dmaqueue *dma_q)
{
struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
- int timeout;
+ int timeout, running_time;
DECLARE_WAITQUEUE(wait, current);
dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
(unsigned long)dma_q);
add_wait_queue(&dma_q->wq, &wait);
- if (!kthread_should_stop()) {
- dma_q->frame++;
-
- /* Calculate time to wake up */
- timeout = dma_q->ini_jiffies+
- msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR * 1000)
- / WAKE_DENOMINATOR) - jiffies;
-
- if (timeout <= 0) {
- int old = dma_q->frame;
- dma_q->frame = (jiffies_to_msecs(jiffies -
- dma_q->ini_jiffies) *
- WAKE_DENOMINATOR) /
- (WAKE_NUMERATOR * 1000) + 1;
-
- timeout = dma_q->ini_jiffies+
- msecs_to_jiffies((dma_q->frame *
- WAKE_NUMERATOR * 1000)
- / WAKE_DENOMINATOR) - jiffies;
-
- dprintk(dev, 1, "underrun, losed %d frames. "
- "Now, frame is %d. Waking on %d jiffies\n",
- dma_q->frame-old, dma_q->frame, timeout);
- } else
- dprintk(dev, 1, "will sleep for %i jiffies\n",
- timeout);
-
- vivi_thread_tick(dma_q);
-
- schedule_timeout_interruptible(timeout);
- }
+ if (kthread_should_stop())
+ goto stop_task;
+
+ running_time = jiffies - dma_q->ini_jiffies;
+ dma_q->frame++;
+
+ /* Calculate time to wake up */
+ timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - running_time;
+
+ if (timeout > msecs_to_jiffies(frames_to_ms(2)) || timeout <= 0) {
+ int old = dma_q->frame;
+ int nframes;
+
+ dma_q->frame = (jiffies_to_msecs(running_time) /
+ frames_to_ms(1)) + 1;
+
+ timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame))
+ - running_time;
+
+ if (unlikely (timeout <= 0))
+ timeout = 1;
+ nframes = (dma_q->frame > old)?
+ dma_q->frame - old : old - dma_q->frame;
+
+ dprintk(dev, 1, "%ld: %s %d frames. "
+ "Current frame is %d. Will sleep for %d jiffies\n",
+ jiffies,
+ (dma_q->frame > old)? "Underrun, losed" : "Overrun of",
+ nframes, dma_q->frame, timeout);
+ } else
+ dprintk(dev, 1, "will sleep for %d jiffies\n", timeout);
+
+ vivi_thread_tick(dma_q);
+
+ schedule_timeout_interruptible(timeout);
+
+stop_task:
remove_wait_queue(&dma_q->wq, &wait);
try_to_freeze();
}
struct vivi_dmaqueue *vidq = &dev->vidq;
struct vivi_buffer *buf;
+ spin_lock(&dev->slock);
+
while (!list_empty(&vidq->active)) {
buf = list_entry(vidq->active.next,
struct vivi_buffer, vb.queue);
wake_up(&buf->vb.done);
printk(KERN_INFO "vivi/0: [%p/%d] timeout\n", buf, buf->vb.i);
}
-
restart_video_queue(vidq);
+
+ spin_unlock(&dev->slock);
}
/* ------------------------------------------------------------------
dev->h = 0;
dev->m = 0;
dev->s = 0;
- dev->us = 0;
+ dev->ms = 0;
dev->mv_count = 0;
dev->jiffies = jiffies;
sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
- dev->h, dev->m, dev->s, (dev->us + 500) / 1000);
+ dev->h, dev->m, dev->s, dev->ms);
videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops,
- NULL, NULL, fh->type, V4L2_FIELD_INTERLACED,
+ NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
sizeof(struct vivi_buffer), fh);
return 0;
/* initialize locks */
mutex_init(&dev->lock);
+ spin_lock_init(&dev->slock);
dev->vidq.timeout.function = vivi_vid_timeout;
dev->vidq.timeout.data = (unsigned long)dev;