[PATCH 3/3] can: xilinx_can: Add debugfs support for ECC

Srinivas Goud srinivas.goud at amd.com
Mon Jun 12 04:42:57 PDT 2023


Create debugfs entry for reading all the FIFO ECC errors.

Signed-off-by: Srinivas Goud <srinivas.goud at amd.com>
---
 drivers/net/can/xilinx_can.c | 62 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 311e435..f7bf31a 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -29,6 +29,7 @@
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
 #include <linux/pm_runtime.h>
+#include <linux/debugfs.h>
 
 #define DRIVER_NAME	"xilinx_can"
 
@@ -183,6 +184,9 @@ enum xcan_reg {
 #define XCAN_FLAG_RX_FIFO_MULTI	0x0010
 #define XCAN_FLAG_CANFD_2	0x0020
 
+/* ECC counters buffer length */
+#define XCAN_ECC_CNT_BUF_LEN	100
+
 enum xcan_ip_type {
 	XAXI_CAN = 0,
 	XZYNQ_CANPS,
@@ -222,6 +226,7 @@ struct xcan_devtype_data {
  * @ecc_1bit_txolfifo_cnt:	TXOLFIFO 1bit ECC count
  * @ecc_2bit_txtlfifo_cnt:	TXTLFIFO 2bit ECC count
  * @ecc_1bit_txtlfifo_cnt:	TXTLFIFO 1bit ECC count
+ * @debugfs:			Directory entry for debugfs
  */
 struct xcan_priv {
 	struct can_priv can;
@@ -246,6 +251,7 @@ struct xcan_priv {
 	u32 ecc_1bit_txolfifo_cnt;
 	u32 ecc_2bit_txtlfifo_cnt;
 	u32 ecc_1bit_txtlfifo_cnt;
+	struct dentry *debugfs;
 };
 
 /* CAN Bittiming constants as per Xilinx CAN specs */
@@ -1736,6 +1742,56 @@ static int __maybe_unused xcan_runtime_resume(struct device *dev)
 	return 0;
 }
 
+static ssize_t read_ecc_cnt_status(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	unsigned int len = 0, buf_len = XCAN_ECC_CNT_BUF_LEN;
+	struct net_device *ndev = file->private_data;
+	struct xcan_priv *priv = netdev_priv(ndev);
+	ssize_t ret_cnt;
+	char *buf;
+
+	buf = kzalloc(buf_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	len = scnprintf(buf + len, buf_len - len,
+			"%d\n", priv->ecc_2bit_rxfifo_cnt);
+	len += scnprintf(buf + len, buf_len - len,
+			"%d\n", priv->ecc_1bit_rxfifo_cnt);
+	len += scnprintf(buf + len, buf_len - len,
+			"%d\n", priv->ecc_2bit_txolfifo_cnt);
+	len += scnprintf(buf + len, buf_len - len,
+			"%d\n", priv->ecc_1bit_txolfifo_cnt);
+	len += scnprintf(buf + len, buf_len - len,
+			"%d\n", priv->ecc_2bit_txtlfifo_cnt);
+	len += scnprintf(buf + len, buf_len - len,
+			"%d\n", priv->ecc_1bit_txtlfifo_cnt);
+	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+	kfree(buf);
+
+	return ret_cnt;
+}
+
+static const struct file_operations read_ecc_fops = {
+	.open = simple_open,
+	.read = read_ecc_cnt_status,
+	.llseek = generic_file_llseek,
+};
+
+static void setup_debugfs(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+
+	priv->debugfs = debugfs_create_dir(dev_name(priv->dev), NULL);
+	if (!priv->debugfs)
+		return;
+
+	debugfs_create_file("read_ecc_cnt", 0644, priv->debugfs,
+			    ndev, &read_ecc_fops);
+}
+
 static const struct dev_pm_ops xcan_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(xcan_suspend, xcan_resume)
 	SET_RUNTIME_PM_OPS(xcan_runtime_suspend, xcan_runtime_resume, NULL)
@@ -1974,10 +2030,12 @@ static int xcan_probe(struct platform_device *pdev)
 		   priv->reg_base, ndev->irq, priv->can.clock.freq,
 		   hw_tx_max, priv->tx_max);
 
-	if (priv->ecc_enable)
+	if (priv->ecc_enable) {
+		setup_debugfs(ndev);
 		/* Reset FIFO ECC counters */
 		priv->write_reg(priv, XCAN_ECC_CFG_OFFSET, XCAN_ECC_CFG_REECRX_MASK |
 			XCAN_ECC_CFG_REECTXOL_MASK | XCAN_ECC_CFG_REECTXTL_MASK);
+	}
 
 	return 0;
 
@@ -2000,7 +2058,9 @@ static int xcan_probe(struct platform_device *pdev)
 static int xcan_remove(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct xcan_priv *priv = netdev_priv(ndev);
 
+	debugfs_remove_recursive(priv->debugfs);
 	unregister_candev(ndev);
 	pm_runtime_disable(&pdev->dev);
 	free_candev(ndev);
-- 
2.1.1




More information about the linux-arm-kernel mailing list