forked from luck/tmp_suning_uos_patched
[SCSI] mpt2sas : release diagnotic buffers prior host reset
Diagnostic buffer support is already there in the driver. This support allows applications to pull ring buffers from controller firmware for debugging firmware related issues. What this patch does is sends reqeust to firmware to release the buffers prior to host reset. This will allow what ever debug info is there prior to reset to be dma'd to host memory. With out this fix, some of the debug data would been lost. Signed-off-by: Eric Moore <eric.moore@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
8901cbb45e
commit
99bb214b1b
|
@ -64,6 +64,9 @@
|
|||
static struct fasync_struct *async_queue;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
|
||||
|
||||
static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type,
|
||||
u8 *issue_reset);
|
||||
|
||||
/**
|
||||
* enum block_state - blocking state
|
||||
* @NON_BLOCKING: non blocking
|
||||
|
@ -378,10 +381,22 @@ _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp)
|
|||
void
|
||||
mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
|
||||
{
|
||||
int i;
|
||||
u8 issue_reset;
|
||||
|
||||
switch (reset_phase) {
|
||||
case MPT2_IOC_PRE_RESET:
|
||||
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
|
||||
"MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
|
||||
for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
|
||||
if (!(ioc->diag_buffer_status[i] &
|
||||
MPT2_DIAG_BUFFER_IS_REGISTERED))
|
||||
continue;
|
||||
if ((ioc->diag_buffer_status[i] &
|
||||
MPT2_DIAG_BUFFER_IS_RELEASED))
|
||||
continue;
|
||||
_ctl_send_release(ioc, i, &issue_reset);
|
||||
}
|
||||
break;
|
||||
case MPT2_IOC_AFTER_RESET:
|
||||
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
|
||||
|
@ -395,6 +410,17 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
|
|||
case MPT2_IOC_DONE_RESET:
|
||||
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
|
||||
"MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
|
||||
|
||||
for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
|
||||
if (!(ioc->diag_buffer_status[i] &
|
||||
MPT2_DIAG_BUFFER_IS_REGISTERED))
|
||||
continue;
|
||||
if ((ioc->diag_buffer_status[i] &
|
||||
MPT2_DIAG_BUFFER_IS_RELEASED))
|
||||
continue;
|
||||
ioc->diag_buffer_status[i] |=
|
||||
MPT2_DIAG_BUFFER_IS_DIAG_RESET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1552,6 +1578,105 @@ _ctl_diag_query(void __user *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _ctl_send_release - Diag Release Message
|
||||
* @ioc: per adapter object
|
||||
* @buffer_type - specifies either TRACE or SNAPSHOT
|
||||
* @issue_reset - specifies whether host reset is required.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
_ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
|
||||
{
|
||||
Mpi2DiagReleaseRequest_t *mpi_request;
|
||||
Mpi2DiagReleaseReply_t *mpi_reply;
|
||||
u16 smid;
|
||||
u16 ioc_status;
|
||||
u32 ioc_state;
|
||||
int rc;
|
||||
unsigned long timeleft;
|
||||
|
||||
dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
|
||||
__func__));
|
||||
|
||||
rc = 0;
|
||||
*issue_reset = 0;
|
||||
|
||||
ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
|
||||
if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
|
||||
dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
|
||||
"skipping due to FAULT state\n", ioc->name,
|
||||
__func__));
|
||||
rc = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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",
|
||||
ioc->name, __func__);
|
||||
rc = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ioc->ctl_cmds.status = MPT2_CMD_PENDING;
|
||||
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
|
||||
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
|
||||
ioc->ctl_cmds.smid = smid;
|
||||
|
||||
mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
|
||||
mpi_request->BufferType = buffer_type;
|
||||
|
||||
mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
|
||||
timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
|
||||
printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
|
||||
__func__);
|
||||
_debug_dump_mf(mpi_request,
|
||||
sizeof(Mpi2DiagReleaseRequest_t)/4);
|
||||
if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
|
||||
*issue_reset = 1;
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* process the completed Reply Message Frame */
|
||||
if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
|
||||
printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
|
||||
ioc->name, __func__);
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mpi_reply = ioc->ctl_cmds.reply;
|
||||
ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
|
||||
|
||||
if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
|
||||
ioc->diag_buffer_status[buffer_type] |=
|
||||
MPT2_DIAG_BUFFER_IS_RELEASED;
|
||||
dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
|
||||
ioc->name, __func__));
|
||||
} else {
|
||||
printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
|
||||
"log_info(0x%08x)\n", ioc->name, __func__,
|
||||
ioc_status, mpi_reply->IOCLogInfo);
|
||||
rc = -EFAULT;
|
||||
}
|
||||
|
||||
out:
|
||||
ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* _ctl_diag_release - request to send Diag Release Message to firmware
|
||||
* @arg - user space buffer containing ioctl content
|
||||
|
@ -1568,12 +1693,7 @@ _ctl_diag_release(void __user *arg, enum block_state state)
|
|||
struct MPT2SAS_ADAPTER *ioc;
|
||||
void *request_data;
|
||||
int rc;
|
||||
Mpi2DiagReleaseRequest_t *mpi_request;
|
||||
Mpi2DiagReleaseReply_t *mpi_reply;
|
||||
u8 buffer_type;
|
||||
unsigned long timeleft;
|
||||
u16 smid;
|
||||
u16 ioc_status;
|
||||
u8 issue_reset = 0;
|
||||
|
||||
if (copy_from_user(&karg, arg, sizeof(karg))) {
|
||||
|
@ -1623,80 +1743,30 @@ _ctl_diag_release(void __user *arg, enum block_state state)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* buffers were released by due to host reset */
|
||||
if ((ioc->diag_buffer_status[buffer_type] &
|
||||
MPT2_DIAG_BUFFER_IS_DIAG_RESET)) {
|
||||
ioc->diag_buffer_status[buffer_type] |=
|
||||
MPT2_DIAG_BUFFER_IS_RELEASED;
|
||||
ioc->diag_buffer_status[buffer_type] &=
|
||||
~MPT2_DIAG_BUFFER_IS_DIAG_RESET;
|
||||
printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
|
||||
"was released due to host reset\n", ioc->name, __func__,
|
||||
buffer_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
rc = _ctl_send_release(ioc, buffer_type, &issue_reset);
|
||||
|
||||
smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
|
||||
if (!smid) {
|
||||
printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
|
||||
ioc->name, __func__);
|
||||
rc = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
ioc->ctl_cmds.status = MPT2_CMD_PENDING;
|
||||
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
|
||||
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
|
||||
ioc->ctl_cmds.smid = smid;
|
||||
|
||||
mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
|
||||
mpi_request->BufferType = buffer_type;
|
||||
|
||||
mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
|
||||
timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
|
||||
printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
|
||||
__func__);
|
||||
_debug_dump_mf(mpi_request,
|
||||
sizeof(Mpi2DiagReleaseRequest_t)/4);
|
||||
if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
|
||||
issue_reset = 1;
|
||||
goto issue_host_reset;
|
||||
}
|
||||
|
||||
/* process the completed Reply Message Frame */
|
||||
if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
|
||||
printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
|
||||
ioc->name, __func__);
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mpi_reply = ioc->ctl_cmds.reply;
|
||||
ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
|
||||
|
||||
if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
|
||||
ioc->diag_buffer_status[buffer_type] |=
|
||||
MPT2_DIAG_BUFFER_IS_RELEASED;
|
||||
dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
|
||||
ioc->name, __func__));
|
||||
} else {
|
||||
printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
|
||||
"log_info(0x%08x)\n", ioc->name, __func__,
|
||||
ioc_status, mpi_reply->IOCLogInfo);
|
||||
rc = -EFAULT;
|
||||
}
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset)
|
||||
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
|
||||
out:
|
||||
|
||||
ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
|
||||
mutex_unlock(&ioc->ctl_cmds.mutex);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -295,8 +295,9 @@ struct mpt2_ioctl_btdh_mapping {
|
|||
|
||||
|
||||
/* status bits for ioc->diag_buffer_status */
|
||||
#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
|
||||
#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
|
||||
#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
|
||||
#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
|
||||
#define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04)
|
||||
|
||||
/* application flags for mpt2_diag_register, mpt2_diag_query */
|
||||
#define MPT2_APP_FLAGS_APP_OWNED (0x0001)
|
||||
|
|
Loading…
Reference in New Issue
Block a user