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