From patchwork Thu Sep 29 23:35:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serge Semin X-Patchwork-Id: 12994756 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F2230C433FE for ; Thu, 29 Sep 2022 23:43:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=LIEGzQzcWauy1HceRUuB913zYm5cmcn4FqErjUipqek=; b=F4IcrdMGfWWMWz Ahpju+bDUOsgEfDgZkPjjhLBE8ia4yMWIXYN2FlUYSJz5dzECXOwODAuG4mSDf35rpbRAda0tW86o HpangRy9BZ2vkbEEiuaAb2UjEziIj2szEpkLP7x+qfwStvrFvdAmVNPScGmNnLpnI4FZyYDXOUqNU 0u0t2FW+EisNuEnPgv5ujUL4QBFrib7xAE07b6lbwb4mKdlw8m67zv7kxMYtaxOtbsjuST1bZ7zfB cQ6gXjqz90Xj2dcDew3bNshXbc+rybTKedfXo2sVV7alKUSXrbdSqqfn65xAt4fSM5E/XZrLTHpzg wa30F9em0bY/c36TmEkA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oe3AK-0063Fh-Fy; Thu, 29 Sep 2022 23:42:06 +0000 Received: from post.baikalelectronics.com ([213.79.110.86]) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oe34z-0060pz-1v for linux-arm-kernel@lists.infradead.org; Thu, 29 Sep 2022 23:36:36 +0000 Received: from post.baikalelectronics.com (localhost.localdomain [127.0.0.1]) by post.baikalelectronics.com (Proxmox) with ESMTP id D0730E0ED1; Fri, 30 Sep 2022 02:36:31 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= baikalelectronics.ru; h=cc:cc:content-transfer-encoding :content-type:content-type:date:from:from:in-reply-to:message-id :mime-version:references:reply-to:subject:subject:to:to; s=post; bh=KwyTjzyrYNEk+t6o0jftTpBsKJZt6rkkthg6rtDJxmo=; b=e62heODP16sy DbIiprblRcI8bjvBG+q9iPcX4NTWXYlDCgzE83YrXHAT59ElB6M5uH3cGE7MJb3F SPA4um1/95cQqDZxIHLlBwa0yx2yYOf0SO4OmS6b/c0ZCivSQd61oaT2Xjx1FXVn yAMo9+UELWtobuNdk61cSx4is5B1tqs= Received: from mail.baikal.int (mail.baikal.int [192.168.51.25]) by post.baikalelectronics.com (Proxmox) with ESMTP id C16CCE0E70; Fri, 30 Sep 2022 02:36:31 +0300 (MSK) Received: from localhost (192.168.168.10) by mail (192.168.51.25) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Fri, 30 Sep 2022 02:36:32 +0300 From: Serge Semin To: Michal Simek , Borislav Petkov , Mauro Carvalho Chehab , Tony Luck , James Morse , Robert Richter CC: Serge Semin , Serge Semin , Alexey Malahov , Michail Ivanov , Pavel Parkhomenko , Punnaiah Choudary Kalluri , Manish Narani , Dinh Nguyen , , , Subject: [PATCH RESEND v3 01/18] EDAC/synopsys: Convert sysfs nodes to debugfs ones Date: Fri, 30 Sep 2022 02:35:13 +0300 Message-ID: <20220929233530.13016-2-Sergey.Semin@baikalelectronics.ru> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20220929233530.13016-1-Sergey.Semin@baikalelectronics.ru> References: <20220929233530.13016-1-Sergey.Semin@baikalelectronics.ru> MIME-Version: 1.0 X-Originating-IP: [192.168.168.10] X-ClientProxiedBy: MAIL.baikal.int (192.168.51.25) To mail (192.168.51.25) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220929_163633_325063_D60215B4 X-CRM114-Status: GOOD ( 22.31 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The DW uMCTL2 DDRC EDAC driver supports creating two sysfs nodes: "inject_data_error" and "inject_data_poison". First of them is responsible for setting the error-injecting physical address up. The second one is supposed to be used to enable the hardware capability of the correctable and uncorrectable error injection. As you can see the semantics of these nodes is pure debug. They are even created only if the EDAC_DEBUG kernel config is enabled. Thus there is no point in having these nodes exported in the sysfs. Let's move them to DebugFS in the device private directory as this should have been done in the first place. While at it we suggest to move the address map initialization procedure invocation to the DebugFS nodes creating function and create an empty snps_create_debugfs_nodes() method in case if the EDAC_DEBUG config is disabled. Thus the DW uMCTL2 DDRC EDAC probe procedure will get to be a bit simpler. Signed-off-by: Serge Semin --- drivers/edac/synopsys_edac.c | 221 +++++++++++++++++++---------------- 1 file changed, 122 insertions(+), 99 deletions(-) diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 7833bcff3e2e..b2a2f938045c 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -640,6 +641,16 @@ static int snps_setup_irq(struct mem_ctl_info *mci, struct platform_device *pdev #ifdef CONFIG_EDAC_DEBUG +#define SNPS_DEBUGFS_FOPS(__name, __read, __write) \ + static const struct file_operations __name = { \ + .owner = THIS_MODULE, \ + .open = simple_open, \ + .read = __read, \ + .write = __write, \ + } + +#define SNPS_DBGFS_BUF_LEN 128 + /** * snps_data_poison_setup - Update poison registers. * @priv: DDR memory controller private instance data. @@ -700,90 +711,6 @@ static void snps_data_poison_setup(struct snps_edac_priv *priv) writel(regval, priv->baseaddr + ECC_POISON1_OFST); } -static ssize_t inject_data_error_show(struct device *dev, - struct device_attribute *mattr, - char *data) -{ - struct mem_ctl_info *mci = to_mci(dev); - struct snps_edac_priv *priv = mci->pvt_info; - - return sprintf(data, "Poison0 Addr: 0x%08x\n\rPoison1 Addr: 0x%08x\n\r" - "Error injection Address: 0x%lx\n\r", - readl(priv->baseaddr + ECC_POISON0_OFST), - readl(priv->baseaddr + ECC_POISON1_OFST), - priv->poison_addr); -} - -static ssize_t inject_data_error_store(struct device *dev, - struct device_attribute *mattr, - const char *data, size_t count) -{ - struct mem_ctl_info *mci = to_mci(dev); - struct snps_edac_priv *priv = mci->pvt_info; - - if (kstrtoul(data, 0, &priv->poison_addr)) - return -EINVAL; - - snps_data_poison_setup(priv); - - return count; -} - -static ssize_t inject_data_poison_show(struct device *dev, - struct device_attribute *mattr, - char *data) -{ - struct mem_ctl_info *mci = to_mci(dev); - struct snps_edac_priv *priv = mci->pvt_info; - const char *errstr; - u32 regval; - - regval = readl(priv->baseaddr + ECC_CFG1_OFST); - errstr = FIELD_GET(ECC_CEPOISON_MASK, regval) == ECC_CEPOISON_MASK ? - "Correctable Error" : "UnCorrectable Error"; - - return sprintf(data, "Data Poisoning: %s\n\r", errstr); -} - -static ssize_t inject_data_poison_store(struct device *dev, - struct device_attribute *mattr, - const char *data, size_t count) -{ - struct mem_ctl_info *mci = to_mci(dev); - struct snps_edac_priv *priv = mci->pvt_info; - - writel(0, priv->baseaddr + DDR_SWCTL); - if (strncmp(data, "CE", 2) == 0) - writel(ECC_CEPOISON_MASK, priv->baseaddr + ECC_CFG1_OFST); - else - writel(ECC_UEPOISON_MASK, priv->baseaddr + ECC_CFG1_OFST); - writel(1, priv->baseaddr + DDR_SWCTL); - - return count; -} - -static DEVICE_ATTR_RW(inject_data_error); -static DEVICE_ATTR_RW(inject_data_poison); - -static int snps_create_sysfs_attributes(struct mem_ctl_info *mci) -{ - int rc; - - rc = device_create_file(&mci->dev, &dev_attr_inject_data_error); - if (rc < 0) - return rc; - rc = device_create_file(&mci->dev, &dev_attr_inject_data_poison); - if (rc < 0) - return rc; - return 0; -} - -static void snps_remove_sysfs_attributes(struct mem_ctl_info *mci) -{ - device_remove_file(&mci->dev, &dev_attr_inject_data_error); - device_remove_file(&mci->dev, &dev_attr_inject_data_poison); -} - static void snps_setup_row_address_map(struct snps_edac_priv *priv, u32 *addrmap) { u32 addrmap_row_b2_10; @@ -1004,7 +931,115 @@ static void snps_setup_address_map(struct snps_edac_priv *priv) snps_setup_rank_address_map(priv, addrmap); } -#endif /* CONFIG_EDAC_DEBUG */ + +static ssize_t snps_inject_data_error_read(struct file *filep, char __user *ubuf, + size_t size, loff_t *offp) +{ + struct mem_ctl_info *mci = filep->private_data; + struct snps_edac_priv *priv = mci->pvt_info; + char buf[SNPS_DBGFS_BUF_LEN]; + int pos; + + pos = scnprintf(buf, sizeof(buf), "Poison0 Addr: 0x%08x\n\r", + readl(priv->baseaddr + ECC_POISON0_OFST)); + pos += scnprintf(buf + pos, sizeof(buf) - pos, "Poison1 Addr: 0x%08x\n\r", + readl(priv->baseaddr + ECC_POISON1_OFST)); + pos += scnprintf(buf + pos, sizeof(buf) - pos, "Error injection Address: 0x%lx\n\r", + priv->poison_addr); + + return simple_read_from_buffer(ubuf, size, offp, buf, pos); +} + +static ssize_t snps_inject_data_error_write(struct file *filep, const char __user *ubuf, + size_t size, loff_t *offp) +{ + struct mem_ctl_info *mci = filep->private_data; + struct snps_edac_priv *priv = mci->pvt_info; + int rc; + + rc = kstrtoul_from_user(ubuf, size, 0, &priv->poison_addr); + if (rc) + return rc; + + snps_data_poison_setup(priv); + + return size; +} + +SNPS_DEBUGFS_FOPS(snps_inject_data_error, snps_inject_data_error_read, + snps_inject_data_error_write); + +static ssize_t snps_inject_data_poison_read(struct file *filep, char __user *ubuf, + size_t size, loff_t *offp) +{ + struct mem_ctl_info *mci = filep->private_data; + struct snps_edac_priv *priv = mci->pvt_info; + char buf[SNPS_DBGFS_BUF_LEN]; + const char *errstr; + u32 regval; + int pos; + + regval = readl(priv->baseaddr + ECC_CFG1_OFST); + errstr = FIELD_GET(ECC_CEPOISON_MASK, regval) == ECC_CEPOISON_MASK ? + "Correctable Error" : "UnCorrectable Error"; + + pos = scnprintf(buf, sizeof(buf), "Data Poisoning: %s\n\r", errstr); + + return simple_read_from_buffer(ubuf, size, offp, buf, pos); +} + +static ssize_t snps_inject_data_poison_write(struct file *filep, const char __user *ubuf, + size_t size, loff_t *offp) +{ + struct mem_ctl_info *mci = filep->private_data; + struct snps_edac_priv *priv = mci->pvt_info; + char buf[SNPS_DBGFS_BUF_LEN]; + int rc; + + rc = simple_write_to_buffer(buf, sizeof(buf), offp, ubuf, size); + if (rc < 0) + return rc; + + writel(0, priv->baseaddr + DDR_SWCTL); + if (strncmp(buf, "CE", 2) == 0) + writel(ECC_CEPOISON_MASK, priv->baseaddr + ECC_CFG1_OFST); + else + writel(ECC_UEPOISON_MASK, priv->baseaddr + ECC_CFG1_OFST); + writel(1, priv->baseaddr + DDR_SWCTL); + + return size; +} + +SNPS_DEBUGFS_FOPS(snps_inject_data_poison, snps_inject_data_poison_read, + snps_inject_data_poison_write); + +/** + * snps_create_debugfs_nodes - Create DebugFS nodes. + * @mci: EDAC memory controller instance. + * + * Create DW uMCTL2 EDAC driver DebugFS nodes in the device private + * DebugFS directory. + * + * Return: none. + */ +static void snps_create_debugfs_nodes(struct mem_ctl_info *mci) +{ + struct snps_edac_priv *priv = mci->pvt_info; + + snps_setup_address_map(priv); + + edac_debugfs_create_file("inject_data_error", 0600, mci->debugfs, mci, + &snps_inject_data_error); + + edac_debugfs_create_file("inject_data_poison", 0600, mci->debugfs, mci, + &snps_inject_data_poison); +} + +#else /* !CONFIG_EDAC_DEBUG */ + +static inline void snps_create_debugfs_nodes(struct mem_ctl_info *mci) {} + +#endif /* !CONFIG_EDAC_DEBUG */ /** * snps_mc_probe - Check controller and bind driver. @@ -1070,17 +1105,9 @@ static int snps_mc_probe(struct platform_device *pdev) goto free_edac_mc; } -#ifdef CONFIG_EDAC_DEBUG - rc = snps_create_sysfs_attributes(mci); - if (rc) { - edac_printk(KERN_ERR, EDAC_MC, "Failed to create sysfs entries\n"); - goto free_edac_mc; - } + snps_create_debugfs_nodes(mci); - snps_setup_address_map(priv); -#endif - - return rc; + return 0; free_edac_mc: edac_mc_free(mci); @@ -1101,10 +1128,6 @@ static int snps_mc_remove(struct platform_device *pdev) snps_disable_irq(priv); -#ifdef CONFIG_EDAC_DEBUG - snps_remove_sysfs_attributes(mci); -#endif - edac_mc_del_mc(&pdev->dev); edac_mc_free(mci);