18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Debugfs interface Support for MPT (Message Passing Technology) based 48c2ecf20Sopenharmony_ci * controllers. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2020 Broadcom Inc. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Authors: Broadcom Inc. 98c2ecf20Sopenharmony_ci * Sreekanth Reddy <sreekanth.reddy@broadcom.com> 108c2ecf20Sopenharmony_ci * Suganath Prabu <suganath-prabu.subramani@broadcom.com> 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Send feedback to : MPT-FusionLinux.pdl@broadcom.com) 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci **/ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/types.h> 188c2ecf20Sopenharmony_ci#include <linux/pci.h> 198c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 208c2ecf20Sopenharmony_ci#include <linux/compat.h> 218c2ecf20Sopenharmony_ci#include <linux/uio.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <scsi/scsi.h> 248c2ecf20Sopenharmony_ci#include <scsi/scsi_device.h> 258c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 268c2ecf20Sopenharmony_ci#include "mpt3sas_base.h" 278c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic struct dentry *mpt3sas_debugfs_root; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * _debugfs_iocdump_read - copy ioc dump from debugfs buffer 338c2ecf20Sopenharmony_ci * @filep: File Pointer 348c2ecf20Sopenharmony_ci * @ubuf: Buffer to fill data 358c2ecf20Sopenharmony_ci * @cnt: Length of the buffer 368c2ecf20Sopenharmony_ci * @ppos: Offset in the file 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic ssize_t 408c2ecf20Sopenharmony_ci_debugfs_iocdump_read(struct file *filp, char __user *ubuf, size_t cnt, 418c2ecf20Sopenharmony_ci loff_t *ppos) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci struct mpt3sas_debugfs_buffer *debug = filp->private_data; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (!debug || !debug->buf) 478c2ecf20Sopenharmony_ci return 0; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci return simple_read_from_buffer(ubuf, cnt, ppos, debug->buf, debug->len); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* 538c2ecf20Sopenharmony_ci * _debugfs_iocdump_open : open the ioc_dump debugfs attribute file 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_cistatic int 568c2ecf20Sopenharmony_ci_debugfs_iocdump_open(struct inode *inode, struct file *file) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci struct MPT3SAS_ADAPTER *ioc = inode->i_private; 598c2ecf20Sopenharmony_ci struct mpt3sas_debugfs_buffer *debug; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci debug = kzalloc(sizeof(struct mpt3sas_debugfs_buffer), GFP_KERNEL); 628c2ecf20Sopenharmony_ci if (!debug) 638c2ecf20Sopenharmony_ci return -ENOMEM; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci debug->buf = (void *)ioc; 668c2ecf20Sopenharmony_ci debug->len = sizeof(struct MPT3SAS_ADAPTER); 678c2ecf20Sopenharmony_ci file->private_data = debug; 688c2ecf20Sopenharmony_ci return 0; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* 728c2ecf20Sopenharmony_ci * _debugfs_iocdump_release : release the ioc_dump debugfs attribute 738c2ecf20Sopenharmony_ci * @inode: inode structure to the corresponds device 748c2ecf20Sopenharmony_ci * @file: File pointer 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_cistatic int 778c2ecf20Sopenharmony_ci_debugfs_iocdump_release(struct inode *inode, struct file *file) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci struct mpt3sas_debugfs_buffer *debug = file->private_data; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (!debug) 828c2ecf20Sopenharmony_ci return 0; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci file->private_data = NULL; 858c2ecf20Sopenharmony_ci kfree(debug); 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic const struct file_operations mpt3sas_debugfs_iocdump_fops = { 908c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 918c2ecf20Sopenharmony_ci .open = _debugfs_iocdump_open, 928c2ecf20Sopenharmony_ci .read = _debugfs_iocdump_read, 938c2ecf20Sopenharmony_ci .release = _debugfs_iocdump_release, 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/* 978c2ecf20Sopenharmony_ci * mpt3sas_init_debugfs : Create debugfs root for mpt3sas driver 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_civoid mpt3sas_init_debugfs(void) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci mpt3sas_debugfs_root = debugfs_create_dir("mpt3sas", NULL); 1028c2ecf20Sopenharmony_ci if (!mpt3sas_debugfs_root) 1038c2ecf20Sopenharmony_ci pr_info("mpt3sas: Cannot create debugfs root\n"); 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* 1078c2ecf20Sopenharmony_ci * mpt3sas_exit_debugfs : Remove debugfs root for mpt3sas driver 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_civoid mpt3sas_exit_debugfs(void) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci debugfs_remove_recursive(mpt3sas_debugfs_root); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/* 1158c2ecf20Sopenharmony_ci * mpt3sas_setup_debugfs : Setup debugfs per HBA adapter 1168c2ecf20Sopenharmony_ci * ioc: MPT3SAS_ADAPTER object 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_civoid 1198c2ecf20Sopenharmony_cimpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci char name[64]; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "scsi_host%d", ioc->shost->host_no); 1248c2ecf20Sopenharmony_ci if (!ioc->debugfs_root) { 1258c2ecf20Sopenharmony_ci ioc->debugfs_root = 1268c2ecf20Sopenharmony_ci debugfs_create_dir(name, mpt3sas_debugfs_root); 1278c2ecf20Sopenharmony_ci if (!ioc->debugfs_root) { 1288c2ecf20Sopenharmony_ci dev_err(&ioc->pdev->dev, 1298c2ecf20Sopenharmony_ci "Cannot create per adapter debugfs directory\n"); 1308c2ecf20Sopenharmony_ci return; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "ioc_dump"); 1358c2ecf20Sopenharmony_ci ioc->ioc_dump = debugfs_create_file(name, 0444, 1368c2ecf20Sopenharmony_ci ioc->debugfs_root, ioc, &mpt3sas_debugfs_iocdump_fops); 1378c2ecf20Sopenharmony_ci if (!ioc->ioc_dump) { 1388c2ecf20Sopenharmony_ci dev_err(&ioc->pdev->dev, 1398c2ecf20Sopenharmony_ci "Cannot create ioc_dump debugfs file\n"); 1408c2ecf20Sopenharmony_ci debugfs_remove(ioc->debugfs_root); 1418c2ecf20Sopenharmony_ci return; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "host_recovery"); 1458c2ecf20Sopenharmony_ci debugfs_create_u8(name, 0444, ioc->debugfs_root, &ioc->shost_recovery); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* 1508c2ecf20Sopenharmony_ci * mpt3sas_destroy_debugfs : Destroy debugfs per HBA adapter 1518c2ecf20Sopenharmony_ci * @ioc: MPT3SAS_ADAPTER object 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_civoid mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci debugfs_remove_recursive(ioc->debugfs_root); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 158