From patchwork Thu Aug 25 16:45:58 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 1098802 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p7PGl8am009136 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 25 Aug 2011 16:47:29 GMT Received: from canuck.infradead.org ([134.117.69.58]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1Qwd4X-0005Os-Fe; Thu, 25 Aug 2011 16:46:30 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Qwd4X-0006xT-1O; Thu, 25 Aug 2011 16:46:29 +0000 Received: from moutng.kundenserver.de ([212.227.126.186]) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Qwd4C-0006uO-1Y for linux-arm-kernel@lists.infradead.org; Thu, 25 Aug 2011 16:46:09 +0000 Received: from axis700.grange (dslb-094-221-119-065.pools.arcor-ip.net [94.221.119.65]) by mrelayeu.kundenserver.de (node=mreu1) with ESMTP (Nemesis) id 0Mh8jt-1QaovZ04Pp-00MIgP; Thu, 25 Aug 2011 18:46:00 +0200 Received: by axis700.grange (Postfix, from userid 1000) id 87A07189F98; Thu, 25 Aug 2011 18:45:58 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by axis700.grange (Postfix) with ESMTP id 84C41189F95; Thu, 25 Aug 2011 18:45:58 +0200 (CEST) Date: Thu, 25 Aug 2011 18:45:58 +0200 (CEST) From: Guennadi Liakhovetski X-X-Sender: lyakh@axis700.grange To: Linux Media Mailing List Subject: [PATCH 1/2] dmaengine: ipu-idmac: add support for the DMA_PAUSE control In-Reply-To: Message-ID: References: <1314211292-10414-1-git-send-email-g.liakhovetski@gmx.de> MIME-Version: 1.0 X-Provags-ID: V02:K0:qwE+TMyx37E41G/vU5j7cKyqiLCwJqxJX1ANfG4/L49 cGCFn2dv+YKZu/fOblHGT6spjER0g/Qc+r2ES1xLUyMRerlXzc H6vba5O9kDRBfePd+Te9xKs9Kzkj6I3F0ZtLltThBNAOKFTEg8 j8XU8yyyNTOX+U7av1l/NFBPueTXDEmWB0DiqY0YFqBI97BEQN kp+NWlosXrgjxxo77plhDu4J1D2Z5Ii0BrgWWsPTEVlIhhPihk 79plr+ii2deTZI9j16vdgBx97+BiYBK1URnKbwfE8YuPeqttNG hm6nK0Ca9EcNwC/mNIAjOqvutE7t3rET3Xr8LC9XE0M4hkYIOG ZZuj6ibH00f99k7HgnkRNI1c8fSn8bMDxc1BNtykuYfTFt+z1M qqtGzAwXVy3Tg== X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110825_124608_387469_5B37561F X-CRM114-Status: GOOD ( 20.18 ) X-Spam-Score: -0.5 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (-0.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [212.227.126.186 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (g.liakhovetski[at]gmx.de) -0.5 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain Cc: Sakari Ailus , Pawel Osciak , Vinod Koul , linux-kernel@vger.kernel.org, Mauro Carvalho Chehab , Hans Verkuil , Laurent Pinchart , Sascha Hauer , Dan Williams , linux-arm-kernel@lists.infradead.org, Marek Szyprowski X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Thu, 25 Aug 2011 16:47:29 +0000 (UTC) To support multi-size buffers in the mx3_camera V4L2 driver we have to be able to stop DMA on a channel without releasing descriptors and completely halting the hardware. Use the DMA_PAUSE control to implement this mode. Signed-off-by: Guennadi Liakhovetski --- drivers/dma/ipu/ipu_idmac.c | 65 +++++++++++++++++++++++++++--------------- 1 files changed, 42 insertions(+), 23 deletions(-) diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index c1a125e..42cdf1c 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1306,6 +1306,7 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) { callback = descnew->txd.callback; callback_param = descnew->txd.callback_param; + list_del_init(&descnew->list); spin_unlock(&ichan->lock); if (callback) callback(callback_param); @@ -1427,39 +1428,58 @@ static int __idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, { struct idmac_channel *ichan = to_idmac_chan(chan); struct idmac *idmac = to_idmac(chan->device); + struct ipu *ipu = to_ipu(idmac); + struct list_head *list, *tmp; unsigned long flags; int i; - /* Only supports DMA_TERMINATE_ALL */ - if (cmd != DMA_TERMINATE_ALL) - return -ENXIO; + switch (cmd) { + case DMA_PAUSE: + spin_lock_irqsave(&ipu->lock, flags); + ipu_ic_disable_task(ipu, chan->chan_id); - ipu_disable_channel(idmac, ichan, - ichan->status >= IPU_CHANNEL_ENABLED); + /* Return all descriptors into "prepared" state */ + list_for_each_safe(list, tmp, &ichan->queue) + list_del_init(list); - tasklet_disable(&to_ipu(idmac)->tasklet); + ichan->sg[0] = NULL; + ichan->sg[1] = NULL; - /* ichan->queue is modified in ISR, have to spinlock */ - spin_lock_irqsave(&ichan->lock, flags); - list_splice_init(&ichan->queue, &ichan->free_list); + spin_unlock_irqrestore(&ipu->lock, flags); - if (ichan->desc) - for (i = 0; i < ichan->n_tx_desc; i++) { - struct idmac_tx_desc *desc = ichan->desc + i; - if (list_empty(&desc->list)) - /* Descriptor was prepared, but not submitted */ - list_add(&desc->list, &ichan->free_list); + ichan->status = IPU_CHANNEL_INITIALIZED; + break; + case DMA_TERMINATE_ALL: + ipu_disable_channel(idmac, ichan, + ichan->status >= IPU_CHANNEL_ENABLED); - async_tx_clear_ack(&desc->txd); - } + tasklet_disable(&ipu->tasklet); - ichan->sg[0] = NULL; - ichan->sg[1] = NULL; - spin_unlock_irqrestore(&ichan->lock, flags); + /* ichan->queue is modified in ISR, have to spinlock */ + spin_lock_irqsave(&ichan->lock, flags); + list_splice_init(&ichan->queue, &ichan->free_list); - tasklet_enable(&to_ipu(idmac)->tasklet); + if (ichan->desc) + for (i = 0; i < ichan->n_tx_desc; i++) { + struct idmac_tx_desc *desc = ichan->desc + i; + if (list_empty(&desc->list)) + /* Descriptor was prepared, but not submitted */ + list_add(&desc->list, &ichan->free_list); - ichan->status = IPU_CHANNEL_INITIALIZED; + async_tx_clear_ack(&desc->txd); + } + + ichan->sg[0] = NULL; + ichan->sg[1] = NULL; + spin_unlock_irqrestore(&ichan->lock, flags); + + tasklet_enable(&ipu->tasklet); + + ichan->status = IPU_CHANNEL_INITIALIZED; + break; + default: + return -ENOSYS; + } return 0; } @@ -1662,7 +1682,6 @@ static void __exit ipu_idmac_exit(struct ipu *ipu) struct idmac_channel *ichan = ipu->channel + i; idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL, 0); - idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0); } dma_async_device_unregister(&idmac->dma);