Skip to content

Commit

Permalink
[SCSI] mpt2sas: Added command line option diag_buffer_enable.
Browse files Browse the repository at this point in the history
Added command line option diag_buffer_enable. When the command line option is
set, the driver will automatically post diag buffers at driver load time.
The command line option diag_buffer_enable is bitwise, so it's possible to
enable both and/or snapshot + trace buffers.  For trace, the driver will
allocate 1MB buffer, whereas for snapshot its 2MB. The purpose for this is
so the enduser doesn't have to manually use an application to setup diag
buffers for debugging firmware related issues.

Here is some examples
trace:
# insmod mpt2sas.ko diag_buffer_enable=1

snapshot:
# insmod mpt2sas.ko diag_buffer_enable=2

both trace and snapshot:
# insmod mpt2sas.ko diag_buffer_enable=3

Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: Eric Moore <Eric.moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Kashyap, Desai authored and James Bottomley committed Oct 29, 2009
1 parent cef7a12 commit 32e0eb5
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 37 deletions.
13 changes: 13 additions & 0 deletions drivers/scsi/mpt2sas/mpt2sas_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ static int msix_disable = -1;
module_param(msix_disable, int, 0);
MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");

/* diag_buffer_enable is bitwise
* bit 0 set = MPI2_DIAG_BUF_TYPE_TRACE(1)
* bit 1 set = MPI2_DIAG_BUF_TYPE_SNAPSHOT(2)
*
* Either bit can be set, or both
*/
static int diag_buffer_enable;
module_param(diag_buffer_enable, int, 0);
MODULE_PARM_DESC(diag_buffer_enable, " enable diag buffer at driver load "
"time (TRACE=1/SNAP=2/default=0)");

int mpt2sas_fwfault_debug;
MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
"and halt firmware - (default=0)");
Expand Down Expand Up @@ -3588,6 +3599,8 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
goto out_free_resources;

mpt2sas_base_start_watchdog(ioc);
if (diag_buffer_enable != 0)
mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
return 0;

out_free_resources:
Expand Down
3 changes: 3 additions & 0 deletions drivers/scsi/mpt2sas/mpt2sas_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,9 @@ u8 mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventNotificationReply_t *mpi_reply);

void mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc,
u8 bits_to_regsiter);

/* transport shared API */
u8 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u32 reply);
Expand Down
125 changes: 88 additions & 37 deletions drivers/scsi/mpt2sas/mpt2sas_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,18 +1256,15 @@ _ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type)
}

/**
* _ctl_diag_register - application register with driver
* @arg - user space buffer containing ioctl content
* @state - NON_BLOCKING or BLOCKING
* _ctl_diag_register_2 - wrapper for registering diag buffer support
* @ioc: per adapter object
* @diag_register: the diag_register struct passed in from user space
*
* This will allow the driver to setup any required buffers that will be
* needed by firmware to communicate with the driver.
*/
static long
_ctl_diag_register(void __user *arg, enum block_state state)
_ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc,
struct mpt2_diag_register *diag_register)
{
struct mpt2_diag_register karg;
struct MPT2SAS_ADAPTER *ioc;
int rc, i;
void *request_data = NULL;
dma_addr_t request_data_dma;
Expand All @@ -1280,18 +1277,17 @@ _ctl_diag_register(void __user *arg, enum block_state state)
u16 ioc_status;
u8 issue_reset = 0;

if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;

dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
__func__));

buffer_type = karg.buffer_type;
if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
ioc->name, __func__);
rc = -EAGAIN;
goto out;
}

buffer_type = diag_register->buffer_type;
if (!_ctl_diag_capability(ioc, buffer_type)) {
printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
"buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
Expand All @@ -1306,24 +1302,12 @@ _ctl_diag_register(void __user *arg, enum block_state state)
return -EINVAL;
}

if (karg.requested_buffer_size % 4) {
if (diag_register->requested_buffer_size % 4) {
printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size "
"is not 4 byte aligned\n", ioc->name, __func__);
return -EINVAL;
}

if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
return -EAGAIN;
else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
return -ERESTARTSYS;

if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
ioc->name, __func__);
rc = -EAGAIN;
goto out;
}

smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
if (!smid) {
printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
Expand All @@ -1339,12 +1323,12 @@ _ctl_diag_register(void __user *arg, enum block_state state)
ioc->ctl_cmds.smid = smid;

request_data = ioc->diag_buffer[buffer_type];
request_data_sz = karg.requested_buffer_size;
ioc->unique_id[buffer_type] = karg.unique_id;
request_data_sz = diag_register->requested_buffer_size;
ioc->unique_id[buffer_type] = diag_register->unique_id;
ioc->diag_buffer_status[buffer_type] = 0;
memcpy(ioc->product_specific[buffer_type], karg.product_specific,
MPT2_PRODUCT_SPECIFIC_DWORDS);
ioc->diagnostic_flags[buffer_type] = karg.diagnostic_flags;
memcpy(ioc->product_specific[buffer_type],
diag_register->product_specific, MPT2_PRODUCT_SPECIFIC_DWORDS);
ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;

if (request_data) {
request_data_dma = ioc->diag_buffer_dma[buffer_type];
Expand Down Expand Up @@ -1374,8 +1358,8 @@ _ctl_diag_register(void __user *arg, enum block_state state)
}

mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
mpi_request->BufferType = karg.buffer_type;
mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags);
mpi_request->BufferType = diag_register->buffer_type;
mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags);
mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
mpi_request->BufferLength = cpu_to_le32(request_data_sz);
mpi_request->VF_ID = 0; /* TODO */
Expand Down Expand Up @@ -1439,6 +1423,73 @@ _ctl_diag_register(void __user *arg, enum block_state state)
request_data, request_data_dma);

ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
return rc;
}

/**
* mpt2sas_enable_diag_buffer - enabling diag_buffers support driver load time
* @ioc: per adapter object
* @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
*
* This is called when command line option diag_buffer_enable is enabled
* at driver load time.
*/
void
mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register)
{
struct mpt2_diag_register diag_register;

memset(&diag_register, 0, sizeof(struct mpt2_diag_register));

if (bits_to_register & 1) {
printk(MPT2SAS_INFO_FMT "registering trace buffer support\n",
ioc->name);
diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
/* register for 1MB buffers */
diag_register.requested_buffer_size = (1024 * 1024);
diag_register.unique_id = 0x7075900;
_ctl_diag_register_2(ioc, &diag_register);
}

if (bits_to_register & 2) {
printk(MPT2SAS_INFO_FMT "registering snapshot buffer support\n",
ioc->name);
diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
/* register for 2MB buffers */
diag_register.requested_buffer_size = 2 * (1024 * 1024);
diag_register.unique_id = 0x7075901;
_ctl_diag_register_2(ioc, &diag_register);
}
}

/**
* _ctl_diag_register - application register with driver
* @arg - user space buffer containing ioctl content
* @state - NON_BLOCKING or BLOCKING
*
* This will allow the driver to setup any required buffers that will be
* needed by firmware to communicate with the driver.
*/
static long
_ctl_diag_register(void __user *arg, enum block_state state)
{
struct mpt2_diag_register karg;
struct MPT2SAS_ADAPTER *ioc;
long rc;

if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;

if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
return -EAGAIN;
else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
return -ERESTARTSYS;
rc = _ctl_diag_register_2(ioc, &karg);
mutex_unlock(&ioc->ctl_cmds.mutex);
return rc;
}
Expand Down

0 comments on commit 32e0eb5

Please sign in to comment.