scsi: mpt3sas: Capture IOC data for debugging purposes

Information needed to debug driver problems and firmware faults is stored
in the IOC’s MPT3SAS_ADAPTER data structure. Parameters such as IOCFacts,
IOC flags (related to sge, MSI-X, error recovery etc.), performance mode
type, TMs, internal commands reply status, etc. are present.

For debugging purposes, it is therefore helpful to be able to capture this
information so that the fault can be analyzed. Export the MPT3SAS_ADAPTER
data structure in debugfs. The data is available in:

	 /sys/kernel/debug/mpt3sas/scsi_hostX/ioc_dump

Link: https://lore.kernel.org/r/1588056322-29227-1-git-send-email-suganath-prabu.subramani@broadcom.com
Signed-off-by: Suganath Prabu <suganath-prabu.subramani@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Suganath Prabu 2020-04-28 02:45:22 -04:00 committed by Martin K. Petersen
parent 55d4ce458c
commit 2b01b293f3
4 changed files with 179 additions and 4 deletions

View file

@ -7,4 +7,5 @@ mpt3sas-y += mpt3sas_base.o \
mpt3sas_transport.o \
mpt3sas_ctl.o \
mpt3sas_trigger_diag.o \
mpt3sas_warpdrive.o
mpt3sas_warpdrive.o \
mpt3sas_debugfs.o \

View file

@ -76,9 +76,9 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
#define MPT3SAS_DRIVER_VERSION "33.101.00.00"
#define MPT3SAS_MAJOR_VERSION 33
#define MPT3SAS_MINOR_VERSION 101
#define MPT3SAS_DRIVER_VERSION "34.100.00.00"
#define MPT3SAS_MAJOR_VERSION 34
#define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
@ -1472,6 +1472,8 @@ struct MPT3SAS_ADAPTER {
u16 device_remove_in_progress_sz;
u8 is_gen35_ioc;
u8 is_aero_ioc;
struct dentry *debugfs_root;
struct dentry *ioc_dump;
PUT_SMID_IO_FP_HIP put_smid_scsi_io;
PUT_SMID_IO_FP_HIP put_smid_fast_path;
PUT_SMID_IO_FP_HIP put_smid_hi_priority;
@ -1479,6 +1481,11 @@ struct MPT3SAS_ADAPTER {
GET_MSIX_INDEX get_msix_index_for_smlio;
};
struct mpt3sas_debugfs_buffer {
void *buf;
u32 len;
};
#define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
@ -1782,6 +1789,11 @@ mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
/* NCQ Prio Handling Check */
bool scsih_ncq_prio_supp(struct scsi_device *sdev);
void mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_init_debugfs(void);
void mpt3sas_exit_debugfs(void);
/**
* _scsih_is_pcie_scsi_device - determines if device is an pcie scsi device
* @device_info: bitfield providing information about the device.

View file

@ -0,0 +1,158 @@
// 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 <sreekanth.reddy@broadcom.com>
* Suganath Prabu <suganath-prabu.subramani@broadcom.com>
*
* Send feedback to : MPT-FusionLinux.pdl@broadcom.com)
*
**/
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/compat.h>
#include <linux/uio.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include "mpt3sas_base.h"
#include <linux/debugfs.h>
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);
}

View file

@ -9928,6 +9928,7 @@ static void scsih_remove(struct pci_dev *pdev)
&ioc->ioc_pg1_copy);
/* release all the volumes */
_scsih_ir_shutdown(ioc);
mpt3sas_destroy_debugfs(ioc);
sas_remove_host(shost);
list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
list) {
@ -10814,6 +10815,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
scsi_scan_host(shost);
mpt3sas_setup_debugfs(ioc);
return 0;
out_add_shost_fail:
mpt3sas_base_detach(ioc);
@ -11220,6 +11222,7 @@ scsih_init(void)
tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
_scsih_sas_control_complete);
mpt3sas_init_debugfs();
return 0;
}
@ -11251,6 +11254,7 @@ scsih_exit(void)
if (hbas_to_enumerate != 2)
raid_class_release(mpt2sas_raid_template);
sas_release_transport(mpt3sas_transport_template);
mpt3sas_exit_debugfs();
}
/**