From patchwork Tue Jun 2 15:47:16 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 27527 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n52FlDEB014904 for ; Tue, 2 Jun 2009 15:47:13 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753237AbZFBPrD (ORCPT ); Tue, 2 Jun 2009 11:47:03 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756124AbZFBPrD (ORCPT ); Tue, 2 Jun 2009 11:47:03 -0400 Received: from mail.gmx.net ([213.165.64.20]:55059 "HELO mail.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1753237AbZFBPrC (ORCPT ); Tue, 2 Jun 2009 11:47:02 -0400 Received: (qmail invoked by alias); 02 Jun 2009 15:47:02 -0000 Received: from p57BD0669.dip0.t-ipconnect.de (EHLO axis700.grange) [87.189.6.105] by mail.gmx.net (mp008) with SMTP; 02 Jun 2009 17:47:02 +0200 X-Authenticated: #20450766 X-Provags-ID: V01U2FsdGVkX1/xE2BYTcDxU+iGmSciGdkznIKONpcsGr2o0GfxjR D50zpKonN20uem Received: from lyakh (helo=localhost) by axis700.grange with local-esmtp (Exim 4.63) (envelope-from ) id 1MBWCq-0002K2-Fy; Tue, 02 Jun 2009 17:47:16 +0200 Date: Tue, 2 Jun 2009 17:47:16 +0200 (CEST) From: Guennadi Liakhovetski To: Magnus Damm cc: Linux Media Mailing List , morimoto.kuninori@renesas.com, matthieu.castet@parrot.com Subject: [PATCH] sh-mobile-ceu-camera: do not wait for interrupt when releasing buffers In-Reply-To: <20090226103932.30237.96661.sendpatchset@rx1.opensource.se> Message-ID: References: <20090226103932.30237.96661.sendpatchset@rx1.opensource.se> MIME-Version: 1.0 X-Y-GMX-Trusted: 0 X-FuHaFi: 0.45 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Patch [PATCH] video: use videobuf_waiton() in sh_mobile_ceu free_buffer() was not quite correct. It closed a race, but introduced a potential lock-up, if for some reason an interrupt does not come. This has been observed in tests with tw9910. This patch safely dequeues buffers without waiting for their completion. It also moves a buffer state assignment under a spinlock to make it atomic with queuing of the buffer. Signed-off-by: Guennadi Liakhovetski --- -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index d890f8d..67c7dcd 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -296,8 +306,8 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); - vb->state = VIDEOBUF_QUEUED; spin_lock_irqsave(&pcdev->lock, flags); + vb->state = VIDEOBUF_QUEUED; list_add_tail(&vb->queue, &pcdev->capture); if (!pcdev->active) { @@ -311,6 +321,27 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + unsigned long flags; + + spin_lock_irqsave(&pcdev->lock, flags); + + if (pcdev->active == vb) { + /* disable capture (release DMA buffer), reset */ + ceu_write(pcdev, CAPSR, 1 << 16); + pcdev->active = NULL; + } + + if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && + !list_empty(&vb->queue)) { + vb->state = VIDEOBUF_ERROR; + list_del_init(&vb->queue); + } + + spin_unlock_irqrestore(&pcdev->lock, flags); + free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb)); } @@ -330,6 +361,10 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) spin_lock_irqsave(&pcdev->lock, flags); vb = pcdev->active; + if (!vb) + /* Stale interrupt from a released buffer */ + goto out; + list_del_init(&vb->queue); if (!list_empty(&pcdev->capture)) @@ -344,6 +379,8 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); + +out: spin_unlock_irqrestore(&pcdev->lock, flags); return IRQ_HANDLED;