public inbox for linux-edac@vger.kernel.org
 help / color / mirror / Atom feed
From: Serge Semin <fancer.lancer@gmail.com>
To: Michal Simek <michal.simek@amd.com>,
	Alexander Stein <alexander.stein@ew.tq-group.com>,
	Borislav Petkov <bp@alien8.de>, Tony Luck <tony.luck@intel.com>,
	James Morse <james.morse@arm.com>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Robert Richter <rric@kernel.org>
Cc: Serge Semin <fancer.lancer@gmail.com>,
	Punnaiah Choudary Kalluri  <punnaiah.choudary.kalluri@xilinx.com>,
	Dinh Nguyen <dinguyen@kernel.org>, Arnd Bergmann <arnd@arndb.de>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-arm-kernel@lists.infradead.org, linux-edac@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH v4 01/18] EDAC/synopsys: Convert sysfs nodes to debugfs ones
Date: Wed, 20 Sep 2023 22:26:46 +0300	[thread overview]
Message-ID: <20230920192806.29960-2-fancer.lancer@gmail.com> (raw)
In-Reply-To: <20230920192806.29960-1-fancer.lancer@gmail.com>

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 errors injection. 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 especially seeing they aren't listed in the sysfs ABI. Just move
them to the device private directory in DebugFS.

While at it move the address map initialization procedure call to the
DebugFS nodes creating function (it's useless with no DebugFS nodes being
available anyway) 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 and redundant work won't be
performed.

Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
---
 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 327023e35d42..10716f365c6f 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -9,6 +9,7 @@
 #include <linux/bitfield.h>
 #include <linux/bits.h>
 #include <linux/edac.h>
+#include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
@@ -641,6 +642,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.
@@ -701,90 +712,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;
@@ -1005,7 +932,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.
@@ -1071,17 +1106,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);
@@ -1102,10 +1129,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);
 
-- 
2.41.0


  reply	other threads:[~2023-09-20 19:28 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-20 19:26 [PATCH v4 00/18] EDAC/synopsys: Add generic DDRC info and address mapping Serge Semin
2023-09-20 19:26 ` Serge Semin [this message]
2023-09-20 19:26 ` [PATCH v4 02/18] EDAC/mc: Extend memtypes with LPDDR(mDDR) and LPDDR2 Serge Semin
2023-09-20 19:26 ` [PATCH v4 03/18] EDAC/synopsys: Extend memtypes supported by controller Serge Semin
2023-09-20 19:26 ` [PATCH v4 04/18] EDAC/synopsys: Detach private data from mci instance Serge Semin
2023-09-20 19:26 ` [PATCH v4 05/18] EDAC/synopsys: Add DDRC basic parameters infrastructure Serge Semin
2023-09-26  8:07   ` kernel test robot
2023-09-26  8:56     ` Serge Semin
2023-09-20 19:26 ` [PATCH v4 06/18] EDAC/synopsys: Convert plat-data to plat-init function Serge Semin
2023-09-20 19:26 ` [PATCH v4 07/18] EDAC/synopsys: Parse ADDRMAP[7-8] CSRs for (LP)DDR4 only Serge Semin
2023-09-20 19:26 ` [PATCH v4 08/18] EDAC/synopsys: Parse ADDRMAP[0] CSR for multi-ranks case only Serge Semin
2023-09-20 19:26 ` [PATCH v4 09/18] EDAC/synopsys: Set actual DIMM ECC errors grain Serge Semin
2023-09-20 19:26 ` [PATCH v4 10/18] EDAC/synopsys: Get corrected bit position Serge Semin
2023-09-20 19:26 ` [PATCH v4 11/18] EDAC/synopsys: Pass syndrome to EDAC error handler Serge Semin
2023-09-20 19:26 ` [PATCH v4 12/18] EDAC/synopsys: Read full data+ecc pattern on errors Serge Semin
2023-09-20 19:26 ` [PATCH v4 13/18] EDAC/synopsys: Introduce System/SDRAM address translation interface Serge Semin
2023-09-27  7:13   ` kernel test robot
2023-09-20 19:26 ` [PATCH v4 14/18] EDAC/synopsys: Simplify HIF/SDRAM column mapping get procedure Serge Semin
2023-09-20 19:27 ` [PATCH v4 15/18] EDAC/synopsys: Add HIF/SDRAM mapping debugfs node Serge Semin
2023-09-20 19:46 ` [PATCH v4 16/18] EDAC/synopsys: Add erroneous page-frame/offset reporting Serge Semin
2023-09-20 19:50 ` [PATCH v4 17/18] EDAC/synopsys: Add system address regions support Serge Semin
2023-09-20 19:50 ` [PATCH v4 18/18] EDAC/synopsys: Add mapping-based memory size calculation Serge Semin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230920192806.29960-2-fancer.lancer@gmail.com \
    --to=fancer.lancer@gmail.com \
    --cc=alexander.stein@ew.tq-group.com \
    --cc=arnd@arndb.de \
    --cc=bp@alien8.de \
    --cc=dinguyen@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=james.morse@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-edac@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mchehab@kernel.org \
    --cc=michal.simek@amd.com \
    --cc=punnaiah.choudary.kalluri@xilinx.com \
    --cc=rric@kernel.org \
    --cc=tony.luck@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox