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
_debugfs_iocdump_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)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
_debugfs_iocdump_open(struct inode * inode,struct file * file)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
_debugfs_iocdump_release(struct inode * inode,struct file * file)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   */
mpt3sas_init_debugfs(void)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   */
mpt3sas_exit_debugfs(void)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
mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER * ioc)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   */
mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER * ioc)153  void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc)
154  {
155  	debugfs_remove_recursive(ioc->debugfs_root);
156  }
157  
158