// SPDX-License-Identifier: GPL-2.0 /* * Debugfs interface Support for MPT (Message Passing Technology) based * controllers. * * Copyright (C) 2020 Broadcom Inc. * * Authors: Broadcom Inc. * Sreekanth Reddy * Suganath Prabu * * Send feedback to : MPT-FusionLinux.pdl@broadcom.com) * **/ #include #include #include #include #include #include #include #include #include #include #include "mpt3sas_base.h" #include static struct dentry *mpt3sas_debugfs_root; /* * _debugfs_iocdump_read - copy ioc dump from debugfs buffer * @filep: File Pointer * @ubuf: Buffer to fill data * @cnt: Length of the buffer * @ppos: Offset in the file */ static ssize_t _debugfs_iocdump_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct mpt3sas_debugfs_buffer *debug = filp->private_data; if (!debug || !debug->buf) return 0; return simple_read_from_buffer(ubuf, cnt, ppos, debug->buf, debug->len); } /* * _debugfs_iocdump_open : open the ioc_dump debugfs attribute file */ static int _debugfs_iocdump_open(struct inode *inode, struct file *file) { struct MPT3SAS_ADAPTER *ioc = inode->i_private; struct mpt3sas_debugfs_buffer *debug; debug = kzalloc(sizeof(struct mpt3sas_debugfs_buffer), GFP_KERNEL); if (!debug) return -ENOMEM; debug->buf = (void *)ioc; debug->len = sizeof(struct MPT3SAS_ADAPTER); file->private_data = debug; return 0; } /* * _debugfs_iocdump_release : release the ioc_dump debugfs attribute * @inode: inode structure to the corresponds device * @file: File pointer */ static int _debugfs_iocdump_release(struct inode *inode, struct file *file) { struct mpt3sas_debugfs_buffer *debug = file->private_data; if (!debug) return 0; file->private_data = NULL; kfree(debug); return 0; } static const struct file_operations mpt3sas_debugfs_iocdump_fops = { .owner = THIS_MODULE, .open = _debugfs_iocdump_open, .read = _debugfs_iocdump_read, .release = _debugfs_iocdump_release, }; /* * mpt3sas_init_debugfs : Create debugfs root for mpt3sas driver */ void mpt3sas_init_debugfs(void) { mpt3sas_debugfs_root = debugfs_create_dir("mpt3sas", NULL); if (!mpt3sas_debugfs_root) pr_info("mpt3sas: Cannot create debugfs root\n"); } /* * mpt3sas_exit_debugfs : Remove debugfs root for mpt3sas driver */ void mpt3sas_exit_debugfs(void) { debugfs_remove_recursive(mpt3sas_debugfs_root); } /* * mpt3sas_setup_debugfs : Setup debugfs per HBA adapter * ioc: MPT3SAS_ADAPTER object */ void mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc) { char name[64]; snprintf(name, sizeof(name), "scsi_host%d", ioc->shost->host_no); if (!ioc->debugfs_root) { ioc->debugfs_root = debugfs_create_dir(name, mpt3sas_debugfs_root); if (!ioc->debugfs_root) { dev_err(&ioc->pdev->dev, "Cannot create per adapter debugfs directory\n"); return; } } snprintf(name, sizeof(name), "ioc_dump"); ioc->ioc_dump = debugfs_create_file(name, 0444, ioc->debugfs_root, ioc, &mpt3sas_debugfs_iocdump_fops); if (!ioc->ioc_dump) { dev_err(&ioc->pdev->dev, "Cannot create ioc_dump debugfs file\n"); debugfs_remove(ioc->debugfs_root); return; } snprintf(name, sizeof(name), "host_recovery"); debugfs_create_u8(name, 0444, ioc->debugfs_root, &ioc->shost_recovery); } /* * mpt3sas_destroy_debugfs : Destroy debugfs per HBA adapter * @ioc: MPT3SAS_ADAPTER object */ void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc) { debugfs_remove_recursive(ioc->debugfs_root); }