From patchwork Fri Feb 26 14:03:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Appana Durga Kedareswara rao X-Patchwork-Id: 8437291 Return-Path: X-Original-To: patchwork-dmaengine@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 65E109F88A for ; Fri, 26 Feb 2016 14:04:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8A10C20395 for ; Fri, 26 Feb 2016 14:04:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3E67420396 for ; Fri, 26 Feb 2016 14:04:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932865AbcBZOEm (ORCPT ); Fri, 26 Feb 2016 09:04:42 -0500 Received: from mail-bl2nam02on0062.outbound.protection.outlook.com ([104.47.38.62]:18989 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752740AbcBZOEi (ORCPT ); Fri, 26 Feb 2016 09:04:38 -0500 Received: from BL2NAM02FT034.eop-nam02.prod.protection.outlook.com (10.152.76.56) by BL2NAM02HT204.eop-nam02.prod.protection.outlook.com (10.152.76.255) with Microsoft SMTP Server (TLS) id 15.1.422.5; Fri, 26 Feb 2016 14:04:36 +0000 Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.60.83 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.60.83; helo=xsj-pvapsmtpgw01; Received: from xsj-pvapsmtpgw01 (149.199.60.83) by BL2NAM02FT034.mail.protection.outlook.com (10.152.77.161) with Microsoft SMTP Server (TLS) id 15.1.415.6 via Frontend Transport; Fri, 26 Feb 2016 14:04:36 +0000 Received: from unknown-38-66.xilinx.com ([149.199.38.66] helo=xsj-pvapsmtp01) by xsj-pvapsmtpgw01 with esmtp (Exim 4.63) (envelope-from ) id 1aZJ0V-0008NT-Ah; Fri, 26 Feb 2016 06:04:35 -0800 Received: from [127.0.0.1] (helo=localhost) by xsj-pvapsmtp01 with smtp (Exim 4.63) (envelope-from ) id 1aZJ0V-00086s-49; Fri, 26 Feb 2016 06:04:35 -0800 Received: from xsj-pvapsmtp01 (mailhub.xilinx.com [149.199.38.66]) by xsj-smtp-dlp2.xlnx.xilinx.com (8.13.8/8.13.1) with ESMTP id u1QE4DbA023600; Fri, 26 Feb 2016 06:04:14 -0800 Received: from [172.23.64.207] (helo=xhd-lin64re117.xilinx.com) by xsj-pvapsmtp01 with esmtp (Exim 4.63) (envelope-from ) id 1aZJ09-00080c-CP; Fri, 26 Feb 2016 06:04:13 -0800 Received: by xhd-lin64re117.xilinx.com (Postfix, from userid 13614) id 9117620917; Fri, 26 Feb 2016 19:34:12 +0530 (IST) From: Kedareswara rao Appana To: , , , , , , , , CC: , , Subject: [PATCH v3 1/4] dmaengine: xilinx_vdma: Improve SG engine handling Date: Fri, 26 Feb 2016 19:33:51 +0530 Message-ID: <1456495434-11722-1-git-send-email-appanad@xilinx.com> X-Mailer: git-send-email 2.1.2 X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-22156.006 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:149.199.60.83; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(438002)(33646002)(551934003)(5008740100001)(2201001)(4326007)(50226001)(5001960100002)(19580395003)(19580405001)(50466002)(90966002)(106466001)(87936001)(2906002)(52956003)(189998001)(48376002)(6806005)(11100500001)(103686003)(1220700001)(36756003)(50986999)(1096002)(5003940100001)(92566002)(47776003)(4001450100002)(63266004)(46386002)(586003)(86362001)(229853001)(42186005)(45336002)(5001770100001)(107986001)(2101003); DIR:OUT; SFP:1101; SCL:1; SRVR:BL2NAM02HT204; H:xsj-pvapsmtpgw01; FPR:; SPF:Pass; MLV:sfv; LANG:en; MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: f6ca46bc-5925-4a22-338b-08d33eb5c2ab X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(8251501002); SRVR:BL2NAM02HT204; X-Microsoft-Antispam-PRVS: <7a48d8da9d5b40d6ae3ab7682959c073@BL2NAM02HT204.eop-nam02.prod.protection.outlook.com> X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(13023025)(5005006)(13018025)(13017025)(13015025)(13024025)(8121501046)(10201501046)(3002001); SRVR:BL2NAM02HT204; BCL:0; PCL:0; RULEID:; SRVR:BL2NAM02HT204; X-Forefront-PRVS: 0864A36BBF X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Feb 2016 14:04:36.1936 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.60.83]; Helo=[xsj-pvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL2NAM02HT204 Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The current driver allows user to queue up multiple segments on to a single transaction descriptor. User will submit this single desc and in the issue_pending() we decode multiple segments and submit to SG HW engine. We free up the allocated_desc when it is submitted to the HW. Existing code prevents the user to prepare multiple trasactions at same time as we are overwrite with the allocated_desc. The best utilization of HW SG engine would happen if we collate the pending list when we start dma this patch updates the same. Signed-off-by: Kedareswara rao Appana --- Changes for v3: ---> None. Changes for v2: ---> splitted the changes into multiple patches. drivers/dma/xilinx/xilinx_vdma.c | 127 ++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 55 deletions(-) diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c index 6f4b501..06bffec 100644 --- a/drivers/dma/xilinx/xilinx_vdma.c +++ b/drivers/dma/xilinx/xilinx_vdma.c @@ -190,8 +190,7 @@ struct xilinx_vdma_tx_descriptor { * @desc_offset: TX descriptor registers offset * @lock: Descriptor operation lock * @pending_list: Descriptors waiting - * @active_desc: Active descriptor - * @allocated_desc: Allocated descriptor + * @active_list: Descriptors ready to submit * @done_list: Complete descriptors * @common: DMA common channel * @desc_pool: Descriptors pool @@ -206,6 +205,7 @@ struct xilinx_vdma_tx_descriptor { * @tasklet: Cleanup work after irq * @config: Device configuration info * @flush_on_fsync: Flush on Frame sync + * @desc_pendingcount: Descriptor pending count */ struct xilinx_vdma_chan { struct xilinx_vdma_device *xdev; @@ -213,8 +213,7 @@ struct xilinx_vdma_chan { u32 desc_offset; spinlock_t lock; struct list_head pending_list; - struct xilinx_vdma_tx_descriptor *active_desc; - struct xilinx_vdma_tx_descriptor *allocated_desc; + struct list_head active_list; struct list_head done_list; struct dma_chan common; struct dma_pool *desc_pool; @@ -229,6 +228,7 @@ struct xilinx_vdma_chan { struct tasklet_struct tasklet; struct xilinx_vdma_config config; bool flush_on_fsync; + u32 desc_pendingcount; }; /** @@ -342,19 +342,11 @@ static struct xilinx_vdma_tx_descriptor * xilinx_vdma_alloc_tx_descriptor(struct xilinx_vdma_chan *chan) { struct xilinx_vdma_tx_descriptor *desc; - unsigned long flags; - - if (chan->allocated_desc) - return chan->allocated_desc; desc = kzalloc(sizeof(*desc), GFP_KERNEL); if (!desc) return NULL; - spin_lock_irqsave(&chan->lock, flags); - chan->allocated_desc = desc; - spin_unlock_irqrestore(&chan->lock, flags); - INIT_LIST_HEAD(&desc->segments); return desc; @@ -412,9 +404,7 @@ static void xilinx_vdma_free_descriptors(struct xilinx_vdma_chan *chan) xilinx_vdma_free_desc_list(chan, &chan->pending_list); xilinx_vdma_free_desc_list(chan, &chan->done_list); - - xilinx_vdma_free_tx_descriptor(chan, chan->active_desc); - chan->active_desc = NULL; + xilinx_vdma_free_desc_list(chan, &chan->active_list); spin_unlock_irqrestore(&chan->lock, flags); } @@ -614,25 +604,26 @@ static void xilinx_vdma_start(struct xilinx_vdma_chan *chan) static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) { struct xilinx_vdma_config *config = &chan->config; - struct xilinx_vdma_tx_descriptor *desc; + struct xilinx_vdma_tx_descriptor *desc, *tail_desc; unsigned long flags; u32 reg; - struct xilinx_vdma_tx_segment *head, *tail = NULL; + struct xilinx_vdma_tx_segment *tail_segment; if (chan->err) return; spin_lock_irqsave(&chan->lock, flags); - /* There's already an active descriptor, bail out. */ - if (chan->active_desc) - goto out_unlock; - if (list_empty(&chan->pending_list)) goto out_unlock; desc = list_first_entry(&chan->pending_list, struct xilinx_vdma_tx_descriptor, node); + tail_desc = list_last_entry(&chan->pending_list, + struct xilinx_vdma_tx_descriptor, node); + + tail_segment = list_last_entry(&tail_desc->segments, + struct xilinx_vdma_tx_segment, node); /* If it is SG mode and hardware is busy, cannot submit */ if (chan->has_sg && xilinx_vdma_is_running(chan) && @@ -645,14 +636,9 @@ static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) * If hardware is idle, then all descriptors on the running lists are * done, start new transfers */ - if (chan->has_sg) { - head = list_first_entry(&desc->segments, - struct xilinx_vdma_tx_segment, node); - tail = list_entry(desc->segments.prev, - struct xilinx_vdma_tx_segment, node); - - vdma_ctrl_write(chan, XILINX_VDMA_REG_CURDESC, head->phys); - } + if (chan->has_sg) + vdma_ctrl_write(chan, XILINX_VDMA_REG_CURDESC, + desc->async_tx.phys); /* Configure the hardware using info in the config structure */ reg = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR); @@ -694,12 +680,15 @@ static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) /* Start the transfer */ if (chan->has_sg) { - vdma_ctrl_write(chan, XILINX_VDMA_REG_TAILDESC, tail->phys); + vdma_ctrl_write(chan, XILINX_VDMA_REG_TAILDESC, + tail_segment->phys); } else { struct xilinx_vdma_tx_segment *segment, *last = NULL; int i = 0; - list_for_each_entry(segment, &desc->segments, node) { + list_for_each_entry(desc, &chan->pending_list, node) { + segment = list_first_entry(&desc->segments, + struct xilinx_vdma_tx_segment, node); vdma_desc_write(chan, XILINX_VDMA_REG_START_ADDRESS(i++), segment->hw.buf_addr); @@ -716,8 +705,8 @@ static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) vdma_desc_write(chan, XILINX_VDMA_REG_VSIZE, last->hw.vsize); } - list_del(&desc->node); - chan->active_desc = desc; + list_splice_tail_init(&chan->pending_list, &chan->active_list); + chan->desc_pendingcount = 0; out_unlock: spin_unlock_irqrestore(&chan->lock, flags); @@ -742,21 +731,19 @@ static void xilinx_vdma_issue_pending(struct dma_chan *dchan) */ static void xilinx_vdma_complete_descriptor(struct xilinx_vdma_chan *chan) { - struct xilinx_vdma_tx_descriptor *desc; + struct xilinx_vdma_tx_descriptor *desc, *next; unsigned long flags; spin_lock_irqsave(&chan->lock, flags); - desc = chan->active_desc; - if (!desc) { - dev_dbg(chan->dev, "no running descriptors\n"); + if (list_empty(&chan->active_list)) goto out_unlock; - } - - dma_cookie_complete(&desc->async_tx); - list_add_tail(&desc->node, &chan->done_list); - chan->active_desc = NULL; + list_for_each_entry_safe(desc, next, &chan->active_list, node) { + list_del(&desc->node); + dma_cookie_complete(&desc->async_tx); + list_add_tail(&desc->node, &chan->done_list); + } out_unlock: spin_unlock_irqrestore(&chan->lock, flags); @@ -879,6 +866,44 @@ static irqreturn_t xilinx_vdma_irq_handler(int irq, void *data) } /** + * append_desc_queue - Queuing descriptor + * @chan: Driver specific dma channel + * @desc: dma transaction descriptor + */ +static void append_desc_queue(struct xilinx_vdma_chan *chan, + struct xilinx_vdma_tx_descriptor *desc) +{ + struct xilinx_vdma_tx_segment *tail_segment; + struct xilinx_vdma_tx_descriptor *tail_desc; + + if (list_empty(&chan->pending_list)) + goto append; + + /* + * Add the hardware descriptor to the chain of hardware descriptors + * that already exists in memory. + */ + tail_desc = list_last_entry(&chan->pending_list, + struct xilinx_vdma_tx_descriptor, node); + tail_segment = list_last_entry(&tail_desc->segments, + struct xilinx_vdma_tx_segment, node); + tail_segment->hw.next_desc = (u32)desc->async_tx.phys; + + /* + * Add the software descriptor and all children to the list + * of pending transactions + */ +append: + list_add_tail(&desc->node, &chan->pending_list); + chan->desc_pendingcount++; + + if (unlikely(chan->desc_pendingcount > chan->num_frms)) { + dev_dbg(chan->dev, "desc pendingcount is too high\n"); + chan->desc_pendingcount = chan->num_frms; + } +} + +/** * xilinx_vdma_tx_submit - Submit DMA transaction * @tx: Async transaction descriptor * @@ -906,11 +931,8 @@ static dma_cookie_t xilinx_vdma_tx_submit(struct dma_async_tx_descriptor *tx) cookie = dma_cookie_assign(tx); - /* Append the transaction to the pending transactions queue. */ - list_add_tail(&desc->node, &chan->pending_list); - - /* Free the allocated desc */ - chan->allocated_desc = NULL; + /* Put this transaction onto the tail of the pending queue */ + append_desc_queue(chan, desc); spin_unlock_irqrestore(&chan->lock, flags); @@ -973,13 +995,6 @@ xilinx_vdma_dma_prep_interleaved(struct dma_chan *dchan, else hw->buf_addr = xt->src_start; - /* Link the previous next descriptor to current */ - if (!list_empty(&desc->segments)) { - prev = list_last_entry(&desc->segments, - struct xilinx_vdma_tx_segment, node); - prev->hw.next_desc = segment->phys; - } - /* Insert the segment into the descriptor segments list. */ list_add_tail(&segment->node, &desc->segments); @@ -988,7 +1003,7 @@ xilinx_vdma_dma_prep_interleaved(struct dma_chan *dchan, /* Link the last hardware descriptor with the first. */ segment = list_first_entry(&desc->segments, struct xilinx_vdma_tx_segment, node); - prev->hw.next_desc = segment->phys; + desc->async_tx.phys = segment->phys; return &desc->async_tx; @@ -1127,10 +1142,12 @@ static int xilinx_vdma_chan_probe(struct xilinx_vdma_device *xdev, chan->dev = xdev->dev; chan->xdev = xdev; chan->has_sg = xdev->has_sg; + chan->desc_pendingcount = 0x0; spin_lock_init(&chan->lock); INIT_LIST_HEAD(&chan->pending_list); INIT_LIST_HEAD(&chan->done_list); + INIT_LIST_HEAD(&chan->active_list); /* Retrieve the channel properties from the device tree */ has_dre = of_property_read_bool(node, "xlnx,include-dre");