Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b421d24 authored by Asai Thambi S P's avatar Asai Thambi S P Committed by Jens Axboe
Browse files

mtip32xx: Create debugfs entries for troubleshooting



On module load, creates a debugfs parent 'rssd' in debugfs root. Then for each
device, create a new node with corresponding disk name. Under the new node, two
entries 'registers' and 'flags' are created.

NOTE: These entries were removed from sysfs in the previous patch

Signed-off-by: default avatarAsai Thambi S P <asamymuthupa@micron.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 7412ff13
Loading
Loading
Loading
Loading
+161 −1
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/kthread.h>
#include <linux/kthread.h>
#include <../drivers/ata/ahci.h>
#include <../drivers/ata/ahci.h>
#include <linux/export.h>
#include <linux/export.h>
#include <linux/debugfs.h>
#include "mtip32xx.h"
#include "mtip32xx.h"


#define HW_CMD_SLOT_SZ		(MTIP_MAX_COMMAND_SLOTS * 32)
#define HW_CMD_SLOT_SZ		(MTIP_MAX_COMMAND_SLOTS * 32)
@@ -85,6 +86,7 @@ static int instance;
 * allocated in mtip_init().
 * allocated in mtip_init().
 */
 */
static int mtip_major;
static int mtip_major;
static struct dentry *dfs_parent;


static DEFINE_SPINLOCK(rssd_index_lock);
static DEFINE_SPINLOCK(rssd_index_lock);
static DEFINE_IDA(rssd_index_ida);
static DEFINE_IDA(rssd_index_ida);
@@ -2574,6 +2576,120 @@ static ssize_t mtip_hw_show_status(struct device *dev,


static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);
static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);


static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
				  size_t len, loff_t *offset)
{
	struct driver_data *dd =  (struct driver_data *)f->private_data;
	char buf[MTIP_DFS_MAX_BUF_SIZE];
	u32 group_allocated;
	int size = *offset;
	int n;

	if (!len || size)
		return 0;

	if (size < 0)
		return -EINVAL;

	size += sprintf(&buf[size], "H/ S ACTive      : [ 0x");

	for (n = dd->slot_groups-1; n >= 0; n--)
		size += sprintf(&buf[size], "%08X ",
					 readl(dd->port->s_active[n]));

	size += sprintf(&buf[size], "]\n");
	size += sprintf(&buf[size], "H/ Command Issue : [ 0x");

	for (n = dd->slot_groups-1; n >= 0; n--)
		size += sprintf(&buf[size], "%08X ",
					readl(dd->port->cmd_issue[n]));

	size += sprintf(&buf[size], "]\n");
	size += sprintf(&buf[size], "H/ Completed     : [ 0x");

	for (n = dd->slot_groups-1; n >= 0; n--)
		size += sprintf(&buf[size], "%08X ",
				readl(dd->port->completed[n]));

	size += sprintf(&buf[size], "]\n");
	size += sprintf(&buf[size], "H/ PORT IRQ STAT : [ 0x%08X ]\n",
				readl(dd->port->mmio + PORT_IRQ_STAT));
	size += sprintf(&buf[size], "H/ HOST IRQ STAT : [ 0x%08X ]\n",
				readl(dd->mmio + HOST_IRQ_STAT));
	size += sprintf(&buf[size], "\n");

	size += sprintf(&buf[size], "L/ Allocated     : [ 0x");

	for (n = dd->slot_groups-1; n >= 0; n--) {
		if (sizeof(long) > sizeof(u32))
			group_allocated =
				dd->port->allocated[n/2] >> (32*(n&1));
		else
			group_allocated = dd->port->allocated[n];
		size += sprintf(&buf[size], "%08X ", group_allocated);
	}
	size += sprintf(&buf[size], "]\n");

	size += sprintf(&buf[size], "L/ Commands in Q : [ 0x");

	for (n = dd->slot_groups-1; n >= 0; n--) {
		if (sizeof(long) > sizeof(u32))
			group_allocated =
				dd->port->cmds_to_issue[n/2] >> (32*(n&1));
		else
			group_allocated = dd->port->cmds_to_issue[n];
		size += sprintf(&buf[size], "%08X ", group_allocated);
	}
	size += sprintf(&buf[size], "]\n");

	*offset = size <= len ? size : len;
	size = copy_to_user(ubuf, buf, *offset);
	if (size)
		return -EFAULT;

	return *offset;
}

static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,
				  size_t len, loff_t *offset)
{
	struct driver_data *dd =  (struct driver_data *)f->private_data;
	char buf[MTIP_DFS_MAX_BUF_SIZE];
	int size = *offset;

	if (!len || size)
		return 0;

	if (size < 0)
		return -EINVAL;

	size += sprintf(&buf[size], "Flag-port : [ %08lX ]\n",
							dd->port->flags);
	size += sprintf(&buf[size], "Flag-dd   : [ %08lX ]\n",
							dd->dd_flag);

	*offset = size <= len ? size : len;
	size = copy_to_user(ubuf, buf, *offset);
	if (size)
		return -EFAULT;

	return *offset;
}

static const struct file_operations mtip_regs_fops = {
	.owner  = THIS_MODULE,
	.open   = simple_open,
	.read   = mtip_hw_read_registers,
	.llseek = no_llseek,
};

static const struct file_operations mtip_flags_fops = {
	.owner  = THIS_MODULE,
	.open   = simple_open,
	.read   = mtip_hw_read_flags,
	.llseek = no_llseek,
};

/*
/*
 * Create the sysfs related attributes.
 * Create the sysfs related attributes.
 *
 *
@@ -2615,6 +2731,34 @@ static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj)
	return 0;
	return 0;
}
}


static int mtip_hw_debugfs_init(struct driver_data *dd)
{
	if (!dfs_parent)
		return -1;

	dd->dfs_node = debugfs_create_dir(dd->disk->disk_name, dfs_parent);
	if (IS_ERR_OR_NULL(dd->dfs_node)) {
		dev_warn(&dd->pdev->dev,
			"Error creating node %s under debugfs\n",
						dd->disk->disk_name);
		dd->dfs_node = NULL;
		return -1;
	}

	debugfs_create_file("flags", S_IRUGO, dd->dfs_node, dd,
							&mtip_flags_fops);
	debugfs_create_file("registers", S_IRUGO, dd->dfs_node, dd,
							&mtip_regs_fops);

	return 0;
}

static void mtip_hw_debugfs_exit(struct driver_data *dd)
{
	debugfs_remove_recursive(dd->dfs_node);
}


/*
/*
 * Perform any init/resume time hardware setup
 * Perform any init/resume time hardware setup
 *
 *
@@ -3640,6 +3784,7 @@ skip_create_disk:
		mtip_hw_sysfs_init(dd, kobj);
		mtip_hw_sysfs_init(dd, kobj);
		kobject_put(kobj);
		kobject_put(kobj);
	}
	}
	mtip_hw_debugfs_init(dd);


	if (dd->mtip_svc_handler) {
	if (dd->mtip_svc_handler) {
		set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
		set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
@@ -3665,6 +3810,8 @@ start_service_thread:
	return rv;
	return rv;


kthread_run_error:
kthread_run_error:
	mtip_hw_debugfs_exit(dd);

	/* Delete our gendisk. This also removes the device from /dev */
	/* Delete our gendisk. This also removes the device from /dev */
	del_gendisk(dd->disk);
	del_gendisk(dd->disk);


@@ -3715,6 +3862,7 @@ static int mtip_block_remove(struct driver_data *dd)
			kobject_put(kobj);
			kobject_put(kobj);
		}
		}
	}
	}
	mtip_hw_debugfs_exit(dd);


	/*
	/*
	 * Delete our gendisk structure. This also removes the device
	 * Delete our gendisk structure. This also removes the device
@@ -4062,10 +4210,20 @@ static int __init mtip_init(void)
	}
	}
	mtip_major = error;
	mtip_major = error;


	if (!dfs_parent) {
		dfs_parent = debugfs_create_dir("rssd", NULL);
		if (IS_ERR_OR_NULL(dfs_parent)) {
			printk(KERN_WARNING "Error creating debugfs parent\n");
			dfs_parent = NULL;
		}
	}

	/* Register our PCI operations. */
	/* Register our PCI operations. */
	error = pci_register_driver(&mtip_pci_driver);
	error = pci_register_driver(&mtip_pci_driver);
	if (error)
	if (error) {
		debugfs_remove(dfs_parent);
		unregister_blkdev(mtip_major, MTIP_DRV_NAME);
		unregister_blkdev(mtip_major, MTIP_DRV_NAME);
	}


	return error;
	return error;
}
}
@@ -4082,6 +4240,8 @@ static int __init mtip_init(void)
 */
 */
static void __exit mtip_exit(void)
static void __exit mtip_exit(void)
{
{
	debugfs_remove_recursive(dfs_parent);

	/* Release the allocated major block device number. */
	/* Release the allocated major block device number. */
	unregister_blkdev(mtip_major, MTIP_DRV_NAME);
	unregister_blkdev(mtip_major, MTIP_DRV_NAME);


+4 −0
Original line number Original line Diff line number Diff line
@@ -110,6 +110,8 @@
 #define dbg_printk(format, arg...)
 #define dbg_printk(format, arg...)
#endif
#endif


#define MTIP_DFS_MAX_BUF_SIZE 1024

#define __force_bit2int (unsigned int __force)
#define __force_bit2int (unsigned int __force)


enum {
enum {
@@ -446,6 +448,8 @@ struct driver_data {
	unsigned long dd_flag; /* NOTE: use atomic bit operations on this */
	unsigned long dd_flag; /* NOTE: use atomic bit operations on this */


	struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
	struct task_struct *mtip_svc_handler; /* task_struct of svc thd */

	struct dentry *dfs_node;
};
};


#endif
#endif