staging: pi433: add debugfs interface
authorPaulo Miguel Almeida <paulo.miguel.almeida.rodenas@gmail.com>
Fri, 4 Feb 2022 08:04:32 +0000 (21:04 +1300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 4 Feb 2022 14:25:34 +0000 (15:25 +0100)
This adds debugfs interface that can be used for debugging possible
hardware/software issues.

It currently exposes the following debugfs entries for each SPI device
probed:

  /sys/kernel/debug/pi433/<DEVICE>/regs
  ...

The 'regs' file contains all rf69 uC registers values that are useful
for troubleshooting misconfigurations between 2 devices. It contains one
register per line so it should be easy to use normal filtering tools to
find the registers of interest if needed.

Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Paulo Miguel Almeida <paulo.miguel.almeida.rodenas@gmail.com>
Link: https://lore.kernel.org/r/YfzeEHJcd+qvYGZ8@mail.google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/pi433/pi433_if.c
drivers/staging/pi433/rf69.c
drivers/staging/pi433/rf69.h

index 86ad497417f782c2d2d33245c93cd136752aa43e..4fbac3ccef74d86e8ebec46aaac3e0ced04af9b8 100644 (file)
@@ -41,6 +41,8 @@
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
 #endif
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include "pi433_if.h"
 #include "rf69.h"
@@ -1098,12 +1100,76 @@ static const struct file_operations pi433_fops = {
        .llseek =       no_llseek,
 };
 
+static int pi433_debugfs_regs_show(struct seq_file *m, void *p)
+{
+       struct pi433_device *dev;
+       u8 reg_data[114];
+       int i;
+       char *fmt = "0x%02x, 0x%02x\n";
+       int ret;
+
+       dev = m->private;
+
+       mutex_lock(&dev->tx_fifo_lock);
+       mutex_lock(&dev->rx_lock);
+
+       // wait for on-going operations to finish
+       ret = wait_event_interruptible(dev->rx_wait_queue, !dev->tx_active);
+       if (ret)
+               goto out_unlock;
+
+       ret = wait_event_interruptible(dev->tx_wait_queue, !dev->rx_active);
+       if (ret)
+               goto out_unlock;
+
+       // skip FIFO register (0x0) otherwise this can affect some of uC ops
+       for (i = 1; i < 0x50; i++)
+               reg_data[i] = rf69_read_reg(dev->spi, i);
+
+       reg_data[REG_TESTLNA] = rf69_read_reg(dev->spi, REG_TESTLNA);
+       reg_data[REG_TESTPA1] = rf69_read_reg(dev->spi, REG_TESTPA1);
+       reg_data[REG_TESTPA2] = rf69_read_reg(dev->spi, REG_TESTPA2);
+       reg_data[REG_TESTDAGC] = rf69_read_reg(dev->spi, REG_TESTDAGC);
+       reg_data[REG_TESTAFC] = rf69_read_reg(dev->spi, REG_TESTAFC);
+
+       seq_puts(m, "# reg, val\n");
+
+       for (i = 1; i < 0x50; i++)
+               seq_printf(m, fmt, i, reg_data[i]);
+
+       seq_printf(m, fmt, REG_TESTLNA, reg_data[REG_TESTLNA]);
+       seq_printf(m, fmt, REG_TESTPA1, reg_data[REG_TESTPA1]);
+       seq_printf(m, fmt, REG_TESTPA2, reg_data[REG_TESTPA2]);
+       seq_printf(m, fmt, REG_TESTDAGC, reg_data[REG_TESTDAGC]);
+       seq_printf(m, fmt, REG_TESTAFC, reg_data[REG_TESTAFC]);
+
+out_unlock:
+       mutex_unlock(&dev->rx_lock);
+       mutex_unlock(&dev->tx_fifo_lock);
+
+       return ret;
+}
+
+static int pi433_debugfs_regs_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, pi433_debugfs_regs_show, inode->i_private);
+}
+
+static const struct file_operations debugfs_fops = {
+       .llseek =       seq_lseek,
+       .open =         pi433_debugfs_regs_open,
+       .owner =        THIS_MODULE,
+       .read =         seq_read,
+       .release =      single_release
+};
+
 /*-------------------------------------------------------------------------*/
 
 static int pi433_probe(struct spi_device *spi)
 {
        struct pi433_device     *device;
        int                     retval;
+       struct dentry           *entry;
 
        /* setup spi parameters */
        spi->mode = 0x00;
@@ -1252,6 +1318,10 @@ static int pi433_probe(struct spi_device *spi)
        /* spi setup */
        spi_set_drvdata(spi, device);
 
+       entry = debugfs_create_dir(dev_name(device->dev),
+                                  debugfs_lookup(KBUILD_MODNAME, NULL));
+       debugfs_create_file("regs", 0400, entry, device, &debugfs_fops);
+
        return 0;
 
 del_cdev:
@@ -1275,6 +1345,9 @@ RX_failed:
 static int pi433_remove(struct spi_device *spi)
 {
        struct pi433_device     *device = spi_get_drvdata(spi);
+       struct dentry *mod_entry = debugfs_lookup(KBUILD_MODNAME, NULL);
+
+       debugfs_remove(debugfs_lookup(dev_name(device->dev), mod_entry));
 
        /* free GPIOs */
        free_gpio(device);
@@ -1349,6 +1422,8 @@ static int __init pi433_init(void)
                return PTR_ERR(pi433_class);
        }
 
+       debugfs_create_dir(KBUILD_MODNAME, NULL);
+
        status = spi_register_driver(&pi433_spi_driver);
        if (status < 0) {
                class_destroy(pi433_class);
@@ -1366,6 +1441,7 @@ static void __exit pi433_exit(void)
        spi_unregister_driver(&pi433_spi_driver);
        class_destroy(pi433_class);
        unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name);
+       debugfs_remove_recursive(debugfs_lookup(KBUILD_MODNAME, NULL));
 }
 module_exit(pi433_exit);
 
index c68ad4809e91b8d3210e1a61b70f54d026af1bd6..2ab3bf46e37d4acb6756fe45fdebf45e4b22cff8 100644 (file)
@@ -24,7 +24,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static u8 rf69_read_reg(struct spi_device *spi, u8 addr)
+u8 rf69_read_reg(struct spi_device *spi, u8 addr)
 {
        int retval;
 
index c25942f142a61dbc4cef572cce1a4f3bfa0fa3e4..3ff5609ecf2e11ea95ceb608cdf4413fb7ddb4f7 100644 (file)
@@ -17,6 +17,7 @@
 #define FIFO_SIZE      66              /* bytes */
 #define FIFO_THRESHOLD 15              /* bytes */
 
+u8 rf69_read_reg(struct spi_device *spi, u8 addr);
 int rf69_get_version(struct spi_device *spi);
 int rf69_set_mode(struct spi_device *spi, enum mode mode);
 int rf69_set_data_mode(struct spi_device *spi, u8 data_mode);