From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752267AbdBATtA (ORCPT ); Wed, 1 Feb 2017 14:49:00 -0500 Received: from quartz.orcorp.ca ([184.70.90.242]:44124 "EHLO quartz.orcorp.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752187AbdBATs5 (ORCPT ); Wed, 1 Feb 2017 14:48:57 -0500 From: Jason Gunthorpe To: Greg Kroah-Hartman , atull@opensource.altera.com, Moritz Fischer Cc: linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org Subject: [PATCH v4 fpga 1/4] fpga zynq: Check for errors after completing DMA Date: Wed, 1 Feb 2017 12:48:42 -0700 Message-Id: <1485978525-13676-2-git-send-email-jgunthorpe@obsidianresearch.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1485978525-13676-1-git-send-email-jgunthorpe@obsidianresearch.com> References: <1485978525-13676-1-git-send-email-jgunthorpe@obsidianresearch.com> X-Broken-Reverse-DNS: no host name found for IP address 10.0.0.156 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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); -- 2.7.4