Received: by 2002:a05:7412:37c9:b0:e2:908c:2ebd with SMTP id jz9csp1604571rdb; Wed, 20 Sep 2023 14:07:57 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHXXG1j9MGjRu6pzlQUAVpzBgAcISGB9rbgPL0qK/R8dNH8E6QmNLY2blzV1n14jzcTBsg/ X-Received: by 2002:a05:6a21:9986:b0:154:a1e4:b676 with SMTP id ve6-20020a056a21998600b00154a1e4b676mr3587678pzb.4.1695244077120; Wed, 20 Sep 2023 14:07:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695244077; cv=none; d=google.com; s=arc-20160816; b=rxmcnkE9BW7fd0IJwv/H0ASwgS9BlLUsjt0MKS0s7nlps/LXHgX4RZVISb0nlGoEB6 5rjILxYY6LVv3EYiSW+8W4hpXECBzDnSfTRxs5gcSTg/nhLv3OY7cXUuB2KYaU5xYux4 eib2BokeNVadOEXFcbTYqeG7pplezQFr+BOQ8DU9NTam9FpqN0lbUmMCqLpSbqIl6tjx 0YnO4howiHCsg5s1JTjWrZMIoG0LEWVmKDqdkS+f0De1r+3okjmnIgxQ5kkT+X7OkBQ0 xJeZty0MiEM9dwrlzHC+t29g0RBCWt4VmtM4pr6a/h66HpXezI0+z7A7/CzhUz8b2Qds uuHA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=7q4RipS6b15lvYflfFa1+Nk3GxKwtj41DmLwRyxQ6s0=; fh=eI9qb6tfOyzHw5Ppa14Bu5kyyGZMf4fNTqmOpiM0kZM=; b=0fg+9L03HekAXZFzNZebpLh/TUGGxuNl23en07gx8gjrejvv2x7jRek/WmPX9HqHm9 bRXLOq2sKOPs6wH4tJkchN1w7uTnttgb7ylX4eaNnLgO4tJAB/38FJQRZpVHErgp7NaK 3UZi1JYpqu3NjraA7040Fg2XwrvQxqc/oohyN8sCvUF8YzK4V5oHag8nbH8necyAvvgk JviKb5Uh7V1UJH/sQtZBEfT1XjgwwtlcXwFgbz+v4asiAvPGrcOXrOc6tCH6fnoPLiKD 44KB03OaGrtdUQQrY1lzFdp1JpF8wdvPSn5yklKjhTUCuK0cLHnR76leMHoC5CPaGDkl 2MHA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=hAiTTAki; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from howler.vger.email (howler.vger.email. [2620:137:e000::3:4]) by mx.google.com with ESMTPS id s4-20020a056a00178400b0069100e4252csi577393pfg.105.2023.09.20.14.07.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Sep 2023 14:07:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) client-ip=2620:137:e000::3:4; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=hAiTTAki; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id B2604834F76D; Wed, 20 Sep 2023 12:58:33 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230243AbjITT63 (ORCPT + 99 others); Wed, 20 Sep 2023 15:58:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230238AbjITT6Z (ORCPT ); Wed, 20 Sep 2023 15:58:25 -0400 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF84AEB; Wed, 20 Sep 2023 12:58:13 -0700 (PDT) Received: by mail-lj1-x22d.google.com with SMTP id 38308e7fff4ca-2c12ae20a5cso2593911fa.2; Wed, 20 Sep 2023 12:58:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1695239892; x=1695844692; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7q4RipS6b15lvYflfFa1+Nk3GxKwtj41DmLwRyxQ6s0=; b=hAiTTAkisLTIDWsFsQ0Ut46ivw/HVSXbvmH6TEYh1s3OZUl33j/ONtYMbjKRH9tha3 woQYoM5Ni71n3b9ik2sU+YLxyQA44ynlLSslTx2TgmRoGrf4KHBGYDSvFu4gTFFC3+2g J5x0EUNQh81bQPiPC0V396RJgPeZuqXZ8wuiOBDerjGgCCCWszqna2Xp+8yzKE90I3ul mCvI5EtqF3TO6GyMqqDrp5Rt2wCdUM/Iu0GfxSeYw8YxoI+YfF3D5aQop72NQm20GsED bLz1irtFzvzIre/0ePYIbnFYYMk+CgWHCfwdxZLRiyQBXCckwiNhnKH/T8CJzTNM3K/E xX8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695239892; x=1695844692; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7q4RipS6b15lvYflfFa1+Nk3GxKwtj41DmLwRyxQ6s0=; b=fUzqAPg6MfTKL+NOhxyn33MrjSxI7zRtrNi8xq87/Cme87T2QC0QWyVn7GdLxESBWf 43o6go5gbjwcxzitGsURuU1xIyFfMKEiHn8PR9PxPK8r5lyEh611MQh702m6Gpkx95tl /2zK6FfxLfK5P6/p497PHu3DCjhXQ1IPT1IeBuibsZKLGe3qKtUbvetFd17LSCYZbbfo 4X59PCh0DuBbUbmaFPXd+QppCdBwZYj2fPNkDLYdEiCW+H4zUXMaM79R29bEfbd+z7CE HtW0eAXW8feLsFQVv6mZggXJqM0EalNNi6lRK1ZFduV36127SI7fs7VHUxltYanBHcjP 2iZg== X-Gm-Message-State: AOJu0YztUEzDCrMwyfRwZ+Y4lui6CfuGC3BHfY6Y0rDSlo0gqW3QAgAV Dmd3WdIovo85K3y42aK5YiM= X-Received: by 2002:a05:651c:237:b0:2c0:a2:77e1 with SMTP id z23-20020a05651c023700b002c000a277e1mr3278163ljn.4.1695239892018; Wed, 20 Sep 2023 12:58:12 -0700 (PDT) Received: from localhost ([178.176.85.138]) by smtp.gmail.com with ESMTPSA id a14-20020a2ebe8e000000b002bffb3f8cebsm2010374ljr.54.2023.09.20.12.58.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Sep 2023 12:58:11 -0700 (PDT) From: Serge Semin To: Michal Simek , Alexander Stein , Borislav Petkov , Tony Luck , James Morse , Mauro Carvalho Chehab , Robert Richter , Rob Herring , Krzysztof Kozlowski Cc: Serge Semin , Punnaiah Choudary Kalluri , Dinh Nguyen , Arnd Bergmann , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 07/13] EDAC/synopsys: Split up ECC UE/CE IRQs handler Date: Wed, 20 Sep 2023 22:56:38 +0300 Message-ID: <20230920195720.32047-8-fancer.lancer@gmail.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230920195720.32047-1-fancer.lancer@gmail.com> References: <20230920195720.32047-1-fancer.lancer@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Wed, 20 Sep 2023 12:58:34 -0700 (PDT) DW uMCTL2 DDRC IP-core doesn't have common IRQ line. Instead it provides individual IRQ output signals for each controller events like: corrected error, uncorrected error, DFI parity error, address protection, scrubber done, and so on. So the common IRQ handler implemented in the Synopsys EDAC driver isn't device-specific but is a particular platform specific. Obviously it won't be suitable for the generic devices which are added to the platforms with the original individual IRQs. So split up the common IRQ handler into two ones handling ECC corrected and uncorrected errors. It won't be that hard since both sub-methods it calls are already logically divided into two CE/UE parts. It just implies moving these parts into the dedicated methods and redefining the local variables a bit. The new methods will be simply called from the common IRQs handler if one is utilized on the particular platform. Otherwise each new IRQ handler will be called on particular interrupt request (the IRQ handlers registration will be added a bit later). Note the snps_ecc_status structure is no longer unneeded since the error data is collected and reported now within a single method. So drop it. Signed-off-by: Serge Semin --- drivers/edac/synopsys_edac.c | 273 ++++++++++++++++++----------------- 1 file changed, 137 insertions(+), 136 deletions(-) diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 3735c784fac9..9dde43636199 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -231,7 +231,6 @@ /* ZynqMP DDR QOS Interrupt register definitions */ #define ZYNQMP_DDR_QOS_UE_MASK BIT(2) #define ZYNQMP_DDR_QOS_CE_MASK BIT(1) -#define ZYNQMP_DDR_QOS_IRQ_MASK (ZYNQMP_DDR_QOS_UE_MASK | ZYNQMP_DDR_QOS_CE_MASK) /** * enum snps_dq_width - SDRAM DQ bus width (ECC capable). @@ -373,6 +372,8 @@ struct snps_sdram_addr { /** * struct snps_ecc_error_info - ECC error log information. + * @ecnt: Number of detected errors. + * @syndrome: Error syndrome. * @sdram: SDRAM address. * @syndrome: Error syndrome. * @bitpos: Bit position. @@ -380,6 +381,7 @@ struct snps_sdram_addr { * @ecc: Data ECC. */ struct snps_ecc_error_info { + u16 ecnt; struct snps_sdram_addr sdram; u32 syndrome; u32 bitpos; @@ -387,20 +389,6 @@ struct snps_ecc_error_info { u32 ecc; }; -/** - * struct snps_ecc_status - ECC status information to report. - * @ce_cnt: Correctable error count. - * @ue_cnt: Uncorrectable error count. - * @ceinfo: Correctable error log information. - * @ueinfo: Uncorrectable error log information. - */ -struct snps_ecc_status { - u32 ce_cnt; - u32 ue_cnt; - struct snps_ecc_error_info ceinfo; - struct snps_ecc_error_info ueinfo; -}; - /** * struct snps_edac_priv - DDR memory controller private data. * @info: DDR controller config info. @@ -410,7 +398,6 @@ struct snps_ecc_status { * @baseaddr: Base address of the DDR controller. * @reglock: Concurrent CSRs access lock. * @message: Buffer for framing the event specific info. - * @stat: ECC status information. */ struct snps_edac_priv { struct snps_ddrc_info info; @@ -420,7 +407,6 @@ struct snps_edac_priv { void __iomem *baseaddr; spinlock_t reglock; char message[SNPS_EDAC_MSG_SIZE]; - struct snps_ecc_status stat; }; /** @@ -692,130 +678,179 @@ static inline u32 snps_get_bitpos(u32 syndrome, enum snps_dq_width dq_width) } /** - * snps_get_error_info - Get the current ECC error info. - * @priv: DDR memory controller private instance data. + * snps_ce_irq_handler - Corrected error interrupt handler. + * @irq: IRQ number. + * @dev_id: Device ID. * - * Return: one if there is no error otherwise returns zero. + * Return: IRQ_NONE, if interrupt not set or IRQ_HANDLED otherwise. */ -static int snps_get_error_info(struct snps_edac_priv *priv) +static irqreturn_t snps_ce_irq_handler(int irq, void *dev_id) { - struct snps_ecc_status *p; - u32 regval, clearval; + struct mem_ctl_info *mci = dev_id; + struct snps_edac_priv *priv = mci->pvt_info; + struct snps_ecc_error_info einfo; unsigned long flags; - void __iomem *base; - - base = priv->baseaddr; - p = &priv->stat; + u32 qosval, regval; + dma_addr_t sys; - regval = readl(base + ECC_STAT_OFST); - if (!regval) - return 1; + /* Make sure IRQ is caused by a corrected ECC error */ + if (priv->info.caps & SNPS_CAP_ZYNQMP) { + qosval = readl(priv->baseaddr + ZYNQMP_DDR_QOS_IRQ_STAT_OFST); + if (!(qosval & ZYNQMP_DDR_QOS_CE_MASK)) + return IRQ_NONE; - p->ceinfo.syndrome = FIELD_GET(ECC_STAT_BITNUM_MASK, regval); + qosval &= ZYNQMP_DDR_QOS_CE_MASK; + } - regval = readl(base + ECC_ERRCNT_OFST); - p->ce_cnt = FIELD_GET(ECC_ERRCNT_CECNT_MASK, regval); - p->ue_cnt = FIELD_GET(ECC_ERRCNT_UECNT_MASK, regval); - if (!p->ce_cnt) - goto ue_err; + regval = readl(priv->baseaddr + ECC_STAT_OFST); + if (!FIELD_GET(ECC_STAT_CE_MASK, regval)) + return IRQ_NONE; - p->ceinfo.bitpos = snps_get_bitpos(p->ceinfo.syndrome, priv->info.dq_width); + /* Read error info like syndrome, bit position, SDRAM address, data */ + einfo.syndrome = FIELD_GET(ECC_STAT_BITNUM_MASK, regval); - regval = readl(base + ECC_CEADDR0_OFST); - p->ceinfo.sdram.rank = FIELD_GET(ECC_CEADDR0_RANK_MASK, regval); - p->ceinfo.sdram.row = FIELD_GET(ECC_CEADDR0_ROW_MASK, regval); + einfo.bitpos = snps_get_bitpos(einfo.syndrome, priv->info.dq_width); - regval = readl(base + ECC_CEADDR1_OFST); - p->ceinfo.sdram.bankgrp = FIELD_GET(ECC_CEADDR1_BANKGRP_MASK, regval); - p->ceinfo.sdram.bank = FIELD_GET(ECC_CEADDR1_BANK_MASK, regval); - p->ceinfo.sdram.col = FIELD_GET(ECC_CEADDR1_COL_MASK, regval); + regval = readl(priv->baseaddr + ECC_ERRCNT_OFST); + einfo.ecnt = FIELD_GET(ECC_ERRCNT_CECNT_MASK, regval); - p->ceinfo.data = readl(base + ECC_CSYND0_OFST); - if (priv->info.dq_width == SNPS_DQ_64) - p->ceinfo.data |= (u64)readl(base + ECC_CSYND1_OFST) << 32; + regval = readl(priv->baseaddr + ECC_CEADDR0_OFST); + einfo.sdram.rank = FIELD_GET(ECC_CEADDR0_RANK_MASK, regval); + einfo.sdram.row = FIELD_GET(ECC_CEADDR0_ROW_MASK, regval); - p->ceinfo.ecc = readl(base + ECC_CSYND2_OFST); + regval = readl(priv->baseaddr + ECC_CEADDR1_OFST); + einfo.sdram.bankgrp = FIELD_GET(ECC_CEADDR1_BANKGRP_MASK, regval); + einfo.sdram.bank = FIELD_GET(ECC_CEADDR1_BANK_MASK, regval); + einfo.sdram.col = FIELD_GET(ECC_CEADDR1_COL_MASK, regval); -ue_err: - if (!p->ue_cnt) - goto out; + einfo.data = readl(priv->baseaddr + ECC_CSYND0_OFST); + if (priv->info.dq_width == SNPS_DQ_64) + einfo.data |= (u64)readl(priv->baseaddr + ECC_CSYND1_OFST) << 32; - regval = readl(base + ECC_UEADDR0_OFST); - p->ueinfo.sdram.rank = FIELD_GET(ECC_CEADDR0_RANK_MASK, regval); - p->ueinfo.sdram.row = FIELD_GET(ECC_CEADDR0_ROW_MASK, regval); + einfo.ecc = readl(priv->baseaddr + ECC_CSYND2_OFST); - regval = readl(base + ECC_UEADDR1_OFST); - p->ueinfo.sdram.bankgrp = FIELD_GET(ECC_CEADDR1_BANKGRP_MASK, regval); - p->ueinfo.sdram.bank = FIELD_GET(ECC_CEADDR1_BANK_MASK, regval); - p->ueinfo.sdram.col = FIELD_GET(ECC_CEADDR1_COL_MASK, regval); + /* Report the detected errors with the corresponding sys address */ + snps_map_sdram_to_sys(priv, &einfo.sdram, &sys); - p->ueinfo.data = readl(base + ECC_UESYND0_OFST); - if (priv->info.dq_width == SNPS_DQ_64) - p->ueinfo.data |= (u64)readl(base + ECC_UESYND1_OFST) << 32; + snprintf(priv->message, SNPS_EDAC_MSG_SIZE, + "Row %hu Col %hu Bank %hhu Bank Group %hhu Rank %hhu Bit %d Data 0x%08llx:0x%02x", + einfo.sdram.row, einfo.sdram.col, einfo.sdram.bank, + einfo.sdram.bankgrp, einfo.sdram.rank, + einfo.bitpos, einfo.data, einfo.ecc); - p->ueinfo.ecc = readl(base + ECC_UESYND2_OFST); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, einfo.ecnt, + PHYS_PFN(sys), offset_in_page(sys), + einfo.syndrome, einfo.sdram.rank, 0, -1, + priv->message, ""); -out: + /* Make sure the CE IRQ status is cleared */ spin_lock_irqsave(&priv->reglock, flags); - clearval = readl(base + ECC_CLR_OFST) | - ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT | - ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT; - writel(clearval, base + ECC_CLR_OFST); + regval = readl(priv->baseaddr + ECC_CLR_OFST) | + ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT; + writel(regval, priv->baseaddr + ECC_CLR_OFST); spin_unlock_irqrestore(&priv->reglock, flags); - return 0; + if (priv->info.caps & SNPS_CAP_ZYNQMP) + writel(qosval, priv->baseaddr + ZYNQMP_DDR_QOS_IRQ_STAT_OFST); + + return IRQ_HANDLED; } /** - * snps_handle_error - Handle Correctable and Uncorrectable errors. - * @mci: EDAC memory controller instance. - * @p: Synopsys ECC status structure. + * snps_ue_irq_handler - Uncorrected error interrupt handler. + * @irq: IRQ number. + * @dev_id: Device ID. * - * Handles ECC correctable and uncorrectable errors. + * Return: IRQ_NONE, if interrupt not set or IRQ_HANDLED otherwise. */ -static void snps_handle_error(struct mem_ctl_info *mci, struct snps_ecc_status *p) +static irqreturn_t snps_ue_irq_handler(int irq, void *dev_id) { + struct mem_ctl_info *mci = dev_id; struct snps_edac_priv *priv = mci->pvt_info; - struct snps_ecc_error_info *pinf; + struct snps_ecc_error_info einfo; + unsigned long flags; + u32 qosval, regval; dma_addr_t sys; - if (p->ce_cnt) { - pinf = &p->ceinfo; + /* Make sure IRQ is caused by an uncorrected ECC error */ + if (priv->info.caps & SNPS_CAP_ZYNQMP) { + qosval = readl(priv->baseaddr + ZYNQMP_DDR_QOS_IRQ_STAT_OFST); + if (!(regval & ZYNQMP_DDR_QOS_UE_MASK)) + return IRQ_NONE; - snps_map_sdram_to_sys(priv, &pinf->sdram, &sys); + qosval &= ZYNQMP_DDR_QOS_UE_MASK; + } - snprintf(priv->message, SNPS_EDAC_MSG_SIZE, - "Row %hu Col %hu Bank %hhu Bank Group %hhu Rank %hhu Bit %d Data 0x%08llx:0x%02x", - pinf->sdram.row, pinf->sdram.col, pinf->sdram.bank, - pinf->sdram.bankgrp, pinf->sdram.rank, - pinf->bitpos, pinf->data, pinf->ecc); + regval = readl(priv->baseaddr + ECC_STAT_OFST); + if (!FIELD_GET(ECC_STAT_UE_MASK, regval)) + return IRQ_NONE; - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, p->ce_cnt, - PHYS_PFN(sys), offset_in_page(sys), - pinf->syndrome, pinf->sdram.rank, 0, -1, - priv->message, ""); - } + /* Read error info like SDRAM address, data and syndrome */ + regval = readl(priv->baseaddr + ECC_ERRCNT_OFST); + einfo.ecnt = FIELD_GET(ECC_ERRCNT_UECNT_MASK, regval); - if (p->ue_cnt) { - pinf = &p->ueinfo; + regval = readl(priv->baseaddr + ECC_UEADDR0_OFST); + einfo.sdram.rank = FIELD_GET(ECC_CEADDR0_RANK_MASK, regval); + einfo.sdram.row = FIELD_GET(ECC_CEADDR0_ROW_MASK, regval); - snps_map_sdram_to_sys(priv, &pinf->sdram, &sys); + regval = readl(priv->baseaddr + ECC_UEADDR1_OFST); + einfo.sdram.bankgrp = FIELD_GET(ECC_CEADDR1_BANKGRP_MASK, regval); + einfo.sdram.bank = FIELD_GET(ECC_CEADDR1_BANK_MASK, regval); + einfo.sdram.col = FIELD_GET(ECC_CEADDR1_COL_MASK, regval); - snprintf(priv->message, SNPS_EDAC_MSG_SIZE, - "Row %hu Col %hu Bank %hhu Bank Group %hhu Rank %hhu Data 0x%08llx:0x%02x", - pinf->sdram.row, pinf->sdram.col, pinf->sdram.bank, - pinf->sdram.bankgrp, pinf->sdram.rank, - pinf->data, pinf->ecc); + einfo.data = readl(priv->baseaddr + ECC_UESYND0_OFST); + if (priv->info.dq_width == SNPS_DQ_64) + einfo.data |= (u64)readl(priv->baseaddr + ECC_UESYND1_OFST) << 32; - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, p->ue_cnt, - PHYS_PFN(sys), offset_in_page(sys), - 0, pinf->sdram.rank, 0, -1, - priv->message, ""); - } + einfo.ecc = readl(priv->baseaddr + ECC_UESYND2_OFST); + + /* Report the detected errors with the corresponding sys address */ + snps_map_sdram_to_sys(priv, &einfo.sdram, &sys); + + snprintf(priv->message, SNPS_EDAC_MSG_SIZE, + "Row %hu Col %hu Bank %hhu Bank Group %hhu Rank %hhu Data 0x%08llx:0x%02x", + einfo.sdram.row, einfo.sdram.col, einfo.sdram.bank, + einfo.sdram.bankgrp, einfo.sdram.rank, + einfo.data, einfo.ecc); + + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, einfo.ecnt, + PHYS_PFN(sys), offset_in_page(sys), + 0, einfo.sdram.rank, 0, -1, + priv->message, ""); + + /* Make sure the UE IRQ status is cleared */ + spin_lock_irqsave(&priv->reglock, flags); - memset(p, 0, sizeof(*p)); + regval = readl(priv->baseaddr + ECC_CLR_OFST) | + ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT; + writel(regval, priv->baseaddr + ECC_CLR_OFST); + + spin_unlock_irqrestore(&priv->reglock, flags); + + if (priv->info.caps & SNPS_CAP_ZYNQMP) + writel(qosval, priv->baseaddr + ZYNQMP_DDR_QOS_IRQ_STAT_OFST); + + return IRQ_HANDLED; +} + +/** + * snps_com_irq_handler - Interrupt IRQ signal handler. + * @irq: IRQ number. + * @dev_id: Device ID. + * + * Return: IRQ_NONE, if interrupts not set or IRQ_HANDLED otherwise. + */ +static irqreturn_t snps_com_irq_handler(int irq, void *dev_id) +{ + irqreturn_t rc = IRQ_NONE; + + rc |= snps_ce_irq_handler(irq, dev_id); + + rc |= snps_ue_irq_handler(irq, dev_id); + + return rc; } static void snps_enable_irq(struct snps_edac_priv *priv) @@ -861,40 +896,6 @@ static void snps_disable_irq(struct snps_edac_priv *priv) spin_unlock_irqrestore(&priv->reglock, flags); } -/** - * snps_irq_handler - Interrupt Handler for ECC interrupts. - * @irq: IRQ number. - * @dev_id: Device ID. - * - * Return: IRQ_NONE, if interrupt not set or IRQ_HANDLED otherwise. - */ -static irqreturn_t snps_irq_handler(int irq, void *dev_id) -{ - struct mem_ctl_info *mci = dev_id; - struct snps_edac_priv *priv; - int status, regval; - - priv = mci->pvt_info; - - if (priv->info.caps & SNPS_CAP_ZYNQMP) { - regval = readl(priv->baseaddr + ZYNQMP_DDR_QOS_IRQ_STAT_OFST); - regval &= (ZYNQMP_DDR_QOS_CE_MASK | ZYNQMP_DDR_QOS_UE_MASK); - if (!(regval & ZYNQMP_DDR_QOS_IRQ_MASK)) - return IRQ_NONE; - } - - status = snps_get_error_info(priv); - if (status) - return IRQ_NONE; - - snps_handle_error(mci, &priv->stat); - - if (priv->info.caps & SNPS_CAP_ZYNQMP) - writel(regval, priv->baseaddr + ZYNQMP_DDR_QOS_IRQ_STAT_OFST); - - return IRQ_HANDLED; -} - /** * snps_create_data - Create private data. * @pdev: platform device. @@ -1544,7 +1545,7 @@ static int snps_setup_irq(struct mem_ctl_info *mci) return irq; } - ret = devm_request_irq(&priv->pdev->dev, irq, snps_irq_handler, + ret = devm_request_irq(&priv->pdev->dev, irq, snps_com_irq_handler, 0, dev_name(&priv->pdev->dev), mci); if (ret < 0) { edac_printk(KERN_ERR, EDAC_MC, "Failed to request IRQ\n"); -- 2.41.0