From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752810AbbI3Ao3 (ORCPT ); Tue, 29 Sep 2015 20:44:29 -0400 Received: from mga02.intel.com ([134.134.136.20]:50435 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751696AbbI3AoZ (ORCPT ); Tue, 29 Sep 2015 20:44:25 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.17,610,1437462000"; d="scan'208";a="570912510" From: Ashutosh Dixit To: Greg Kroah-Hartman , Dan Williams , Vinod Koul , linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org Cc: Ashutosh Dixit , Sudeep Dutt , Nikhil Rao , Siva Yerramreddy , Jacek Lawrynowicz Subject: [PATCH char-misc-next v2 05/22] dma: Add support to program MIC x100 status descriptiors Date: Tue, 29 Sep 2015 18:09:37 -0700 Message-Id: <8e003194da11abd636dd1dfebbb5895a0ceac932.1443573394.git.ashutosh.dixit@intel.com> X-Mailer: git-send-email 2.0.0.rc3.2.g998f840 In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Siva Yerramreddy The MIC X100 DMA engine has a special status descriptor which writes an 8 byte value to a destination location. This is used to signal completion of all DMA descriptors prior to the status descriptor. This patch add a new DMA engine API which enables updating a destination address with an 8 byte immediate data value. Reviewed-by: Nikhil Rao Reviewed-by: Ashutosh Dixit Signed-off-by: Lawrynowicz, Jacek Signed-off-by: Sudeep Dutt Signed-off-by: Siva Yerramreddy --- drivers/dma/mic_x100_dma.c | 39 ++++++++++++++++++++++++++++++++++++++- include/linux/dmaengine.h | 4 ++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c index 74d9db0..068e920 100644 --- a/drivers/dma/mic_x100_dma.c +++ b/drivers/dma/mic_x100_dma.c @@ -193,8 +193,16 @@ static void mic_dma_prog_intr(struct mic_dma_chan *ch) static int mic_dma_do_dma(struct mic_dma_chan *ch, int flags, dma_addr_t src, dma_addr_t dst, size_t len) { - if (-ENOMEM == mic_dma_prog_memcpy_desc(ch, src, dst, len)) + if (len && -ENOMEM == mic_dma_prog_memcpy_desc(ch, src, dst, len)) { return -ENOMEM; + } else { + /* 3 is the maximum number of status descriptors */ + int ret = mic_dma_avail_desc_ring_space(ch, 3); + + if (ret < 0) + return ret; + } + /* Above mic_dma_prog_memcpy_desc() makes sure we have enough space */ if (flags & DMA_PREP_FENCE) { mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0, @@ -270,6 +278,33 @@ allocate_tx(struct mic_dma_chan *ch) return tx; } +/* Program a status descriptor with dst as address and value to be written */ +static struct dma_async_tx_descriptor * +mic_dma_prep_status_lock(struct dma_chan *ch, dma_addr_t dst, u64 src_val, + unsigned long flags) +{ + struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch); + int result; + + spin_lock(&mic_ch->prep_lock); + result = mic_dma_avail_desc_ring_space(mic_ch, 4); + if (result < 0) + goto error; + mic_dma_prep_status_desc(&mic_ch->desc_ring[mic_ch->head], src_val, dst, + false); + mic_dma_hw_ring_inc_head(mic_ch); + result = mic_dma_do_dma(mic_ch, flags, 0, 0, 0); + if (result < 0) + goto error; + + return allocate_tx(mic_ch); +error: + dev_err(mic_dma_ch_to_device(mic_ch), + "Error enqueueing dma status descriptor, error=%d\n", result); + spin_unlock(&mic_ch->prep_lock); + return NULL; +} + /* * Prepare a memcpy descriptor to be added to the ring. * Note that the temporary descriptor adds an extra overhead of copying the @@ -587,6 +622,8 @@ static int mic_dma_register_dma_device(struct mic_dma_device *mic_dma_dev, mic_dma_free_chan_resources; mic_dma_dev->dma_dev.device_tx_status = mic_dma_tx_status; mic_dma_dev->dma_dev.device_prep_dma_memcpy = mic_dma_prep_memcpy_lock; + mic_dma_dev->dma_dev.device_prep_dma_imm_data = + mic_dma_prep_status_lock; mic_dma_dev->dma_dev.device_prep_dma_interrupt = mic_dma_prep_interrupt_lock; mic_dma_dev->dma_dev.device_issue_pending = mic_dma_issue_pending; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 7ea9184..c47c68e 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -645,6 +645,7 @@ enum dmaengine_alignment { * The function takes a buffer of size buf_len. The callback function will * be called after period_len bytes have been transferred. * @device_prep_interleaved_dma: Transfer expression in a generic way. + * @device_prep_dma_imm_data: DMA's 8 byte immediate data to the dst address * @device_config: Pushes a new configuration to a channel, return 0 or an error * code * @device_pause: Pauses any transfer happening on a channel. Returns @@ -727,6 +728,9 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( struct dma_chan *chan, struct dma_interleaved_template *xt, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_imm_data)( + struct dma_chan *chan, dma_addr_t dst, u64 data, + unsigned long flags); int (*device_config)(struct dma_chan *chan, struct dma_slave_config *config); -- 2.0.0.rc3.2.g998f840