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