1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Debugfs interface Support for MPT (Message Passing Technology) based
4  * controllers.
5  *
6  * Copyright (C) 2020  Broadcom Inc.
7  *
8  * Authors: Broadcom Inc.
9  * Sreekanth Reddy  <sreekanth.reddy@broadcom.com>
10  * Suganath Prabu <suganath-prabu.subramani@broadcom.com>
11  *
12  * Send feedback to : MPT-FusionLinux.pdl@broadcom.com)
13  *
14  **/
15 
16 #include <linux/kernel.h>
17 #include <linux/types.h>
18 #include <linux/pci.h>
19 #include <linux/interrupt.h>
20 #include <linux/compat.h>
21 #include <linux/uio.h>
22 
23 #include <scsi/scsi.h>
24 #include <scsi/scsi_device.h>
25 #include <scsi/scsi_host.h>
26 #include "mpt3sas_base.h"
27 #include <linux/debugfs.h>
28 
29 static struct dentry *mpt3sas_debugfs_root;
30 
31 /*
32  * _debugfs_iocdump_read - copy ioc dump from debugfs buffer
33  * @filep:	File Pointer
34  * @ubuf:	Buffer to fill data
35  * @cnt:	Length of the buffer
36  * @ppos:	Offset in the file
37  */
38 
39 static ssize_t
40 _debugfs_iocdump_read(struct file *filp, char __user *ubuf, size_t cnt,
41 	loff_t *ppos)
42 
43 {
44 	struct mpt3sas_debugfs_buffer *debug = filp->private_data;
45 
46 	if (!debug || !debug->buf)
47 		return 0;
48 
49 	return simple_read_from_buffer(ubuf, cnt, ppos, debug->buf, debug->len);
50 }
51 
52 /*
53  * _debugfs_iocdump_open :	open the ioc_dump debugfs attribute file
54  */
55 static int
56 _debugfs_iocdump_open(struct inode *inode, struct file *file)
57 {
58 	struct MPT3SAS_ADAPTER *ioc = inode->i_private;
59 	struct mpt3sas_debugfs_buffer *debug;
60 
61 	debug = kzalloc(sizeof(struct mpt3sas_debugfs_buffer), GFP_KERNEL);
62 	if (!debug)
63 		return -ENOMEM;
64 
65 	debug->buf = (void *)ioc;
66 	debug->len = sizeof(struct MPT3SAS_ADAPTER);
67 	file->private_data = debug;
68 	return 0;
69 }
70 
71 /*
72  * _debugfs_iocdump_release :	release the ioc_dump debugfs attribute
73  * @inode: inode structure to the corresponds device
74  * @file: File pointer
75  */
76 static int
77 _debugfs_iocdump_release(struct inode *inode, struct file *file)
78 {
79 	struct mpt3sas_debugfs_buffer *debug = file->private_data;
80 
81 	if (!debug)
82 		return 0;
83 
84 	file->private_data = NULL;
85 	kfree(debug);
86 	return 0;
87 }
88 
89 static const struct file_operations mpt3sas_debugfs_iocdump_fops = {
90 	.owner		= THIS_MODULE,
91 	.open           = _debugfs_iocdump_open,
92 	.read           = _debugfs_iocdump_read,
93 	.release        = _debugfs_iocdump_release,
94 };
95 
96 /*
97  * mpt3sas_init_debugfs :	Create debugfs root for mpt3sas driver
98  */
99 void mpt3sas_init_debugfs(void)
100 {
101 	mpt3sas_debugfs_root = debugfs_create_dir("mpt3sas", NULL);
102 	if (!mpt3sas_debugfs_root)
103 		pr_info("mpt3sas: Cannot create debugfs root\n");
104 }
105 
106 /*
107  * mpt3sas_exit_debugfs :	Remove debugfs root for mpt3sas driver
108  */
109 void mpt3sas_exit_debugfs(void)
110 {
111 	debugfs_remove_recursive(mpt3sas_debugfs_root);
112 }
113 
114 /*
115  * mpt3sas_setup_debugfs :	Setup debugfs per HBA adapter
116  * ioc:				MPT3SAS_ADAPTER object
117  */
118 void
119 mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc)
120 {
121 	char name[64];
122 
123 	snprintf(name, sizeof(name), "scsi_host%d", ioc->shost->host_no);
124 	if (!ioc->debugfs_root) {
125 		ioc->debugfs_root =
126 		    debugfs_create_dir(name, mpt3sas_debugfs_root);
127 		if (!ioc->debugfs_root) {
128 			dev_err(&ioc->pdev->dev,
129 			    "Cannot create per adapter debugfs directory\n");
130 			return;
131 		}
132 	}
133 
134 	snprintf(name, sizeof(name), "ioc_dump");
135 	ioc->ioc_dump =	debugfs_create_file(name, 0444,
136 	    ioc->debugfs_root, ioc, &mpt3sas_debugfs_iocdump_fops);
137 	if (!ioc->ioc_dump) {
138 		dev_err(&ioc->pdev->dev,
139 		    "Cannot create ioc_dump debugfs file\n");
140 		debugfs_remove(ioc->debugfs_root);
141 		return;
142 	}
143 
144 	snprintf(name, sizeof(name), "host_recovery");
145 	debugfs_create_u8(name, 0444, ioc->debugfs_root, &ioc->shost_recovery);
146 
147 }
148 
149 /*
150  * mpt3sas_destroy_debugfs :	Destroy debugfs per HBA adapter
151  * @ioc:	MPT3SAS_ADAPTER object
152  */
153 void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc)
154 {
155 	debugfs_remove_recursive(ioc->debugfs_root);
156 }
157 
158