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