From patchwork Fri Jan 6 21:14:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 9501853 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BC8FF606E0 for ; Fri, 6 Jan 2017 21:14:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AECCC2853A for ; Fri, 6 Jan 2017 21:14:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A377628541; Fri, 6 Jan 2017 21:14:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F2EDE2853A for ; Fri, 6 Jan 2017 21:14:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754067AbdAFVOa (ORCPT ); Fri, 6 Jan 2017 16:14:30 -0500 Received: from quartz.orcorp.ca ([184.70.90.242]:50900 "EHLO quartz.orcorp.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753515AbdAFVO2 (ORCPT ); Fri, 6 Jan 2017 16:14:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=obsidianresearch.com; s=rsa1; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=NQqKJ1yxSlSwBXYeXa9QKedoEQDM3MqRmFV/TZoTu5s=; b=fzY8JQUqVy6NeuzFCGuchHAs6ZawI+4/k7t1IIHLwINEsBfZc0pFvOULNnLfOkNlnjxQy/5LhC1jIYevuw8Ys9mDknRcLkvrcG5Qe2SrlS7W2xcb60XZWs5Ot060pZpu8qvmLFXcXxfRcsoH/R2FhRTQ7f4H01ixsFw6QFua7pQ=; Received: from [10.0.0.156] (helo=jggl.edm.orcorp.ca) by quartz.orcorp.ca with esmtps (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1cPbqB-0007E9-2w; Fri, 06 Jan 2017 14:14:23 -0700 From: Jason Gunthorpe To: atull@opensource.altera.com, Moritz Fischer Cc: linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org Subject: [PATCH v3 fpga 1/4] fpga zynq: Check for errors after completing DMA Date: Fri, 6 Jan 2017 14:14:13 -0700 Message-Id: <1483737256-18581-2-git-send-email-jgunthorpe@obsidianresearch.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1483737256-18581-1-git-send-email-jgunthorpe@obsidianresearch.com> References: <1483737256-18581-1-git-send-email-jgunthorpe@obsidianresearch.com> X-Broken-Reverse-DNS: no host name found for IP address 10.0.0.156 Sender: linux-fpga-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fpga@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The completion did not check the interrupt status to see if any error bits were asserted, check error bits and dump some registers if things went wrong. A few fixes are needed to make this work, the IXR_ERROR_FLAGS_MASK was wrong, it included the done bits, which shows a bug in mask/unmask_irqs which were using the wrong bits, simplify all of this stuff. Signed-off-by: Jason Gunthorpe Reviewed-by: Moritz Fischer Acked-by: Alan Tull --- drivers/fpga/zynq-fpga.c | 54 ++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index 1812bf7614e1d4..f674e32832ec44 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -89,7 +89,7 @@ #define IXR_D_P_DONE_MASK BIT(12) /* FPGA programmed */ #define IXR_PCFG_DONE_MASK BIT(2) -#define IXR_ERROR_FLAGS_MASK 0x00F0F860 +#define IXR_ERROR_FLAGS_MASK 0x00F0C860 #define IXR_ALL_MASK 0xF8F7F87F /* Miscellaneous constant values */ @@ -143,23 +143,10 @@ static inline u32 zynq_fpga_read(const struct zynq_fpga_priv *priv, readl_poll_timeout(priv->io_base + addr, val, cond, sleep_us, \ timeout_us) -static void zynq_fpga_mask_irqs(struct zynq_fpga_priv *priv) +/* Cause the specified irq mask bits to generate IRQs */ +static inline void zynq_fpga_set_irq(struct zynq_fpga_priv *priv, u32 enable) { - u32 intr_mask; - - intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET); - zynq_fpga_write(priv, INT_MASK_OFFSET, - intr_mask | IXR_DMA_DONE_MASK | IXR_ERROR_FLAGS_MASK); -} - -static void zynq_fpga_unmask_irqs(struct zynq_fpga_priv *priv) -{ - u32 intr_mask; - - intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET); - zynq_fpga_write(priv, INT_MASK_OFFSET, - intr_mask - & ~(IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK)); + zynq_fpga_write(priv, INT_MASK_OFFSET, ~enable); } static irqreturn_t zynq_fpga_isr(int irq, void *data) @@ -167,7 +154,7 @@ static irqreturn_t zynq_fpga_isr(int irq, void *data) struct zynq_fpga_priv *priv = data; /* disable DMA and error IRQs */ - zynq_fpga_mask_irqs(priv); + zynq_fpga_set_irq(priv, 0); complete(&priv->dma_done); @@ -285,6 +272,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, const char *buf, size_t count) { struct zynq_fpga_priv *priv; + const char *why; int err; char *kbuf; size_t in_count; @@ -312,7 +300,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, reinit_completion(&priv->dma_done); /* enable DMA and error IRQs */ - zynq_fpga_unmask_irqs(priv); + zynq_fpga_set_irq(priv, IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK); /* the +1 in the src addr is used to hold off on DMA_DONE IRQ * until both AXI and PCAP are done ... @@ -331,11 +319,33 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, intr_status = zynq_fpga_read(priv, INT_STS_OFFSET); zynq_fpga_write(priv, INT_STS_OFFSET, intr_status); + if (intr_status & IXR_ERROR_FLAGS_MASK) { + why = "DMA reported error"; + err = -EIO; + goto out_report; + } + if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) { - dev_err(&mgr->dev, "Error configuring FPGA\n"); - err = -EFAULT; + why = "DMA did not complete"; + err = -EIO; + goto out_report; } + err = 0; + goto out_clk; + +out_report: + dev_err(&mgr->dev, + "%s: INT_STS:0x%x CTRL:0x%x LOCK:0x%x INT_MASK:0x%x STATUS:0x%x MCTRL:0x%x\n", + why, + intr_status, + zynq_fpga_read(priv, CTRL_OFFSET), + zynq_fpga_read(priv, LOCK_OFFSET), + zynq_fpga_read(priv, INT_MASK_OFFSET), + zynq_fpga_read(priv, STATUS_OFFSET), + zynq_fpga_read(priv, MCTRL_OFFSET)); + +out_clk: clk_disable(priv->clk); out_free: @@ -452,7 +462,7 @@ static int zynq_fpga_probe(struct platform_device *pdev) /* unlock the device */ zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK); - zynq_fpga_write(priv, INT_MASK_OFFSET, 0xFFFFFFFF); + zynq_fpga_set_irq(priv, 0); zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK); err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev), priv);