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