[SCSI] mpt fusion: rewrite of ioctl_cmds internal generated function

1) rewrite of ioctl_cmds internal generated function that issue commands to
firmware, porting them to be single threaded using the generic MPT_MGMT
struct. All wait Queues are replace by completion Queue.
2) added seperate callback handler for ioctl task managment
(mptctl_taskmgmt_reply), to handle command that timeout
3) rewrite mptctl_bus_reset

Signed-off-by: Kashyap Desai <kadesai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
Kashyap, Desai 2009-05-29 16:46:50 +05:30 committed by James Bottomley
parent e7deff3374
commit ea2a788de4
6 changed files with 393 additions and 319 deletions

View File

@ -434,18 +434,6 @@ do { \
#define MPTCTL_RESET_OK 0x01 /* Issue Bus Reset */ #define MPTCTL_RESET_OK 0x01 /* Issue Bus Reset */
typedef struct _MPT_IOCTL {
struct _MPT_ADAPTER *ioc;
u8 ReplyFrame[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
u8 sense[MPT_SENSE_BUFFER_ALLOC];
int wait_done; /* wake-up value for this ioc */
u8 rsvd;
u8 status; /* current command status */
u8 reset; /* 1 if bus reset allowed */
u8 id; /* target for reset */
struct mutex ioctl_mutex;
} MPT_IOCTL;
#define MPT_MGMT_STATUS_RF_VALID 0x01 /* The Reply Frame is VALID */ #define MPT_MGMT_STATUS_RF_VALID 0x01 /* The Reply Frame is VALID */
#define MPT_MGMT_STATUS_COMMAND_GOOD 0x02 /* Command Status GOOD */ #define MPT_MGMT_STATUS_COMMAND_GOOD 0x02 /* Command Status GOOD */
#define MPT_MGMT_STATUS_PENDING 0x04 /* command is pending */ #define MPT_MGMT_STATUS_PENDING 0x04 /* command is pending */
@ -460,6 +448,10 @@ typedef struct _MPT_IOCTL {
status = MPT_MGMT_STATUS_PENDING; status = MPT_MGMT_STATUS_PENDING;
#define CLEAR_MGMT_STATUS(status) \ #define CLEAR_MGMT_STATUS(status) \
status = 0; status = 0;
#define CLEAR_MGMT_PENDING_STATUS(status) \
status &= ~MPT_MGMT_STATUS_PENDING;
#define SET_MGMT_MSG_CONTEXT(msg_context, value) \
msg_context = value;
typedef struct _MPT_MGMT { typedef struct _MPT_MGMT {
struct mutex mutex; struct mutex mutex;
@ -468,6 +460,7 @@ typedef struct _MPT_MGMT {
u8 sense[MPT_SENSE_BUFFER_ALLOC]; u8 sense[MPT_SENSE_BUFFER_ALLOC];
u8 status; /* current command status */ u8 status; /* current command status */
int completion_code; int completion_code;
u32 msg_context;
} MPT_MGMT; } MPT_MGMT;
/* /*
@ -654,7 +647,6 @@ typedef struct _MPT_ADAPTER
RaidCfgData raid_data; /* Raid config. data */ RaidCfgData raid_data; /* Raid config. data */
SasCfgData sas_data; /* Sas config. data */ SasCfgData sas_data; /* Sas config. data */
FcCfgData fc_data; /* Fc config. data */ FcCfgData fc_data; /* Fc config. data */
MPT_IOCTL *ioctl; /* ioctl data pointer */
struct proc_dir_entry *ioc_dentry; struct proc_dir_entry *ioc_dentry;
struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */
u32 biosVersion; /* BIOS version from IO Unit Page 2 */ u32 biosVersion; /* BIOS version from IO Unit Page 2 */
@ -711,6 +703,7 @@ typedef struct _MPT_ADAPTER
MPT_MGMT mptbase_cmds; /* for sending config pages */ MPT_MGMT mptbase_cmds; /* for sending config pages */
MPT_MGMT internal_cmds; MPT_MGMT internal_cmds;
MPT_MGMT taskmgmt_cmds; MPT_MGMT taskmgmt_cmds;
MPT_MGMT ioctl_cmds;
spinlock_t taskmgmt_lock; /* diagnostic reset lock */ spinlock_t taskmgmt_lock; /* diagnostic reset lock */
int taskmgmt_in_progress; int taskmgmt_in_progress;
u8 taskmgmt_quiesce_io; u8 taskmgmt_quiesce_io;
@ -855,10 +848,8 @@ typedef struct _MPT_SCSI_HOST {
/* Pool of memory for holding SCpnts before doing /* Pool of memory for holding SCpnts before doing
* OS callbacks. freeQ is the free pool. * OS callbacks. freeQ is the free pool.
*/ */
u8 tmPending;
u8 negoNvram; /* DV disabled, nego NVRAM */ u8 negoNvram; /* DV disabled, nego NVRAM */
u8 pad1; u8 pad1;
u8 tmState;
u8 rsvd[2]; u8 rsvd[2];
MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */
struct scsi_cmnd *abortSCpnt; struct scsi_cmnd *abortSCpnt;

View File

@ -84,6 +84,7 @@ MODULE_VERSION(my_VERSION);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS; static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS;
static u8 mptctl_taskmgmt_id = MPT_MAX_PROTOCOL_DRIVERS;
static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait ); static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
@ -127,10 +128,7 @@ static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags
struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
struct buflist *buflist, MPT_ADAPTER *ioc); struct buflist *buflist, MPT_ADAPTER *ioc);
static void mptctl_timeout_expired (MPT_IOCTL *ioctl); static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function);
static int mptctl_bus_reset(MPT_IOCTL *ioctl);
static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd);
static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
/* /*
* Reset Handler cleanup function * Reset Handler cleanup function
@ -183,10 +181,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
int rc = 0; int rc = 0;
if (nonblock) { if (nonblock) {
if (!mutex_trylock(&ioc->ioctl->ioctl_mutex)) if (!mutex_trylock(&ioc->ioctl_cmds.mutex))
rc = -EAGAIN; rc = -EAGAIN;
} else { } else {
if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex)) if (mutex_lock_interruptible(&ioc->ioctl_cmds.mutex))
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
} }
return rc; return rc;
@ -202,100 +200,78 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
static int static int
mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
{ {
char *sense_data; char *sense_data;
int sz, req_index; int req_index;
u16 iocStatus; int sz;
u8 cmd;
if (req) if (!req)
cmd = req->u.hdr.Function; return 0;
else
return 1;
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tcompleting mpi function (0x%02X), req=%p, "
"reply=%p\n", ioc->name, req->u.hdr.Function, req, reply));
if (ioc->ioctl) { dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "completing mpi function "
"(0x%02X), req=%p, reply=%p\n", ioc->name, req->u.hdr.Function,
req, reply));
if (reply==NULL) { /*
* Handling continuation of the same reply. Processing the first
* reply, and eating the other replys that come later.
*/
if (ioc->ioctl_cmds.msg_context != req->u.hdr.MsgContext)
goto out_continuation;
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_reply() NULL Reply " ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
"Function=%x!\n", ioc->name, cmd));
ioc->ioctl->status |= MPT_MGMT_STATUS_COMMAND_GOOD; if (!reply)
ioc->ioctl->reset &= ~MPTCTL_RESET_OK; goto out;
/* We are done, issue wake up ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
*/ sz = min(ioc->reply_sz, 4*reply->u.reply.MsgLength);
ioc->ioctl->wait_done = 1; memcpy(ioc->ioctl_cmds.reply, reply, sz);
wake_up (&mptctl_wait);
return 1;
} if (reply->u.reply.IOCStatus || reply->u.reply.IOCLogInfo)
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"iocstatus (0x%04X), loginfo (0x%08X)\n", ioc->name,
le16_to_cpu(reply->u.reply.IOCStatus),
le32_to_cpu(reply->u.reply.IOCLogInfo)));
/* Copy the reply frame (which much exist if ((req->u.hdr.Function == MPI_FUNCTION_SCSI_IO_REQUEST) ||
* for non-SCSI I/O) to the IOC structure. (req->u.hdr.Function ==
*/ MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
memcpy(ioc->ioctl->ReplyFrame, reply,
min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
ioc->ioctl->status |= MPT_MGMT_STATUS_RF_VALID;
/* Set the command status to GOOD if IOC Status is GOOD if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState)
* OR if SCSI I/O cmd and data underrun or recovered error. dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
*/ "scsi_status (0x%02x), scsi_state (0x%02x), "
iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK; "tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name,
if (iocStatus == MPI_IOCSTATUS_SUCCESS) reply->u.sreply.SCSIStatus,
ioc->ioctl->status |= MPT_MGMT_STATUS_COMMAND_GOOD; reply->u.sreply.SCSIState,
le16_to_cpu(reply->u.sreply.TaskTag),
le32_to_cpu(reply->u.sreply.TransferCount)));
if (iocStatus || reply->u.reply.IOCLogInfo) if (reply->u.sreply.SCSIState &
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tiocstatus (0x%04X), " MPI_SCSI_STATE_AUTOSENSE_VALID) {
"loginfo (0x%08X)\n", ioc->name,
iocStatus,
le32_to_cpu(reply->u.reply.IOCLogInfo)));
if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
(cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState)
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"\tscsi_status (0x%02x), scsi_state (0x%02x), "
"tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name,
reply->u.sreply.SCSIStatus,
reply->u.sreply.SCSIState,
le16_to_cpu(reply->u.sreply.TaskTag),
le32_to_cpu(reply->u.sreply.TransferCount)));
ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
(iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
ioc->ioctl->status |=
MPT_MGMT_STATUS_COMMAND_GOOD;
}
}
/* Copy the sense data - if present
*/
if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
(reply->u.sreply.SCSIState &
MPI_SCSI_STATE_AUTOSENSE_VALID)){
sz = req->u.scsireq.SenseBufferLength; sz = req->u.scsireq.SenseBufferLength;
req_index = req_index =
le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
sense_data = sense_data = ((u8 *)ioc->sense_buf_pool +
((u8 *)ioc->sense_buf_pool +
(req_index * MPT_SENSE_BUFFER_ALLOC)); (req_index * MPT_SENSE_BUFFER_ALLOC));
memcpy(ioc->ioctl->sense, sense_data, sz); memcpy(ioc->ioctl_cmds.sense, sense_data, sz);
ioc->ioctl->status |= MPT_MGMT_STATUS_SENSE_VALID; ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_SENSE_VALID;
} }
if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
mptctl_free_tm_flags(ioc);
/* We are done, issue wake up
*/
ioc->ioctl->wait_done = 1;
wake_up (&mptctl_wait);
} }
out:
/* We are done, issue wake up
*/
if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) {
if (req->u.hdr.Function == MPI_FUNCTION_SCSI_TASK_MGMT)
mpt_clear_taskmgmt_in_progress_flag(ioc);
ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
complete(&ioc->ioctl_cmds.done);
}
out_continuation:
if (reply && (reply->u.reply.MsgFlags &
MPI_MSGFLAGS_CONTINUATION_REPLY))
return 0;
return 1; return 1;
} }
@ -305,30 +281,66 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
* Expecting an interrupt, however timed out. * Expecting an interrupt, however timed out.
* *
*/ */
static void mptctl_timeout_expired (MPT_IOCTL *ioctl) static void
mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
{ {
int rc = 1; unsigned long flags;
if (ioctl == NULL) dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n",
ioc->name, __func__));
if (mpt_fwfault_debug)
mpt_halt_firmware(ioc);
spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
if (ioc->ioc_reset_in_progress) {
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
mpt_free_msg_frame(ioc, mf);
return; return;
dctlprintk(ioctl->ioc,
printk(MYIOC_s_DEBUG_FMT ": Timeout Expired! Host %d\n",
ioctl->ioc->name, ioctl->ioc->id));
ioctl->wait_done = 0;
if (ioctl->reset & MPTCTL_RESET_OK)
rc = mptctl_bus_reset(ioctl);
if (rc) {
/* Issue a reset for this device.
* The IOC is not responding.
*/
dctlprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
ioctl->ioc->name));
mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
} }
return; spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
if (!mptctl_bus_reset(ioc, mf->u.hdr.Function))
return;
/* Issue a reset for this device.
* The IOC is not responding.
*/
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
ioc->name));
CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
mpt_HardResetHandler(ioc, CAN_SLEEP);
mpt_free_msg_frame(ioc, mf);
}
static int
mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
if (!mf)
return 0;
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"TaskMgmt completed (mf=%p, mr=%p)\n",
ioc->name, mf, mr));
ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
if (!mr)
goto out;
ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
memcpy(ioc->taskmgmt_cmds.reply, mr,
min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
out:
if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
mpt_clear_taskmgmt_in_progress_flag(ioc);
ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
complete(&ioc->taskmgmt_cmds.done);
return 1;
}
return 0;
} }
/* mptctl_bus_reset /* mptctl_bus_reset
@ -336,133 +348,150 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
* Bus reset code. * Bus reset code.
* *
*/ */
static int mptctl_bus_reset(MPT_IOCTL *ioctl) static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
{ {
MPT_FRAME_HDR *mf; MPT_FRAME_HDR *mf;
SCSITaskMgmt_t *pScsiTm; SCSITaskMgmt_t *pScsiTm;
MPT_SCSI_HOST *hd; SCSITaskMgmtReply_t *pScsiTmReply;
int ii; int ii;
int retval=0; int retval;
unsigned long timeout;
unsigned long time_count;
u16 iocstatus;
/* bus reset is only good for SCSI IO, RAID PASSTHRU */
ioctl->reset &= ~MPTCTL_RESET_OK; if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) ||
(function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
if (ioctl->ioc->sh == NULL) dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
"TaskMgmt, not SCSI_IO!!\n", ioc->name));
return -EPERM; return -EPERM;
}
hd = shost_priv(ioctl->ioc->sh); mutex_lock(&ioc->taskmgmt_cmds.mutex);
if (hd == NULL) if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
return -EPERM; return -EPERM;
}
/* Single threading .... retval = 0;
*/
if (mptctl_set_tm_flags(hd) != 0)
return -EPERM;
/* Send request /* Send request
*/ */
if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) { mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc);
dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt, no msg frames!!\n", if (mf == NULL) {
ioctl->ioc->name)); dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
"TaskMgmt, no msg frames!!\n", ioc->name));
mptctl_free_tm_flags(ioctl->ioc); mpt_clear_taskmgmt_in_progress_flag(ioc);
return -ENOMEM; retval = -ENOMEM;
goto mptctl_bus_reset_done;
} }
dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
ioctl->ioc->name, mf)); ioc->name, mf));
pScsiTm = (SCSITaskMgmt_t *) mf; pScsiTm = (SCSITaskMgmt_t *) mf;
pScsiTm->TargetID = ioctl->id; memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
pScsiTm->Bus = hd->port; /* 0 */
pScsiTm->ChainOffset = 0;
pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
pScsiTm->Reserved = 0;
pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
pScsiTm->Reserved1 = 0;
pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
pScsiTm->TargetID = 0;
pScsiTm->Bus = 0;
pScsiTm->ChainOffset = 0;
pScsiTm->Reserved = 0;
pScsiTm->Reserved1 = 0;
pScsiTm->TaskMsgContext = 0;
for (ii= 0; ii < 8; ii++) for (ii= 0; ii < 8; ii++)
pScsiTm->LUN[ii] = 0; pScsiTm->LUN[ii] = 0;
for (ii=0; ii < 7; ii++) for (ii=0; ii < 7; ii++)
pScsiTm->Reserved2[ii] = 0; pScsiTm->Reserved2[ii] = 0;
pScsiTm->TaskMsgContext = 0; switch (ioc->bus_type) {
dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT case FC:
"mptctl_bus_reset: issued.\n", ioctl->ioc->name)); timeout = 40;
break;
case SAS:
timeout = 30;
break;
case SPI:
default:
timeout = 2;
break;
}
DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf); dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"TaskMgmt type=%d timeout=%ld\n",
ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout));
ioctl->wait_done=0; INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
if ((ioctl->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && time_count = jiffies;
(ioctl->ioc->facts.MsgVersion >= MPI_VERSION_01_05)) if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
mpt_put_msg_frame_hi_pri(mptctl_id, ioctl->ioc, mf); (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
mpt_put_msg_frame_hi_pri(mptctl_taskmgmt_id, ioc, mf);
else { else {
retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc, retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc,
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP);
if (retval != 0) { if (retval != 0) {
dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!" dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, "TaskMgmt send_handshake FAILED!"
hd->ioc, mf)); " (ioc %p, mf %p, rc=%d) \n", ioc->name,
ioc, mf, retval));
mpt_clear_taskmgmt_in_progress_flag(ioc);
goto mptctl_bus_reset_done; goto mptctl_bus_reset_done;
} }
} }
/* Now wait for the command to complete */ /* Now wait for the command to complete */
ii = wait_event_timeout(mptctl_wait, ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
ioctl->wait_done == 1, if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
HZ*5 /* 5 second timeout */); dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"TaskMgmt failed\n", ioc->name));
mpt_free_msg_frame(ioc, mf);
mpt_clear_taskmgmt_in_progress_flag(ioc);
if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
retval = 0;
else
retval = -1; /* return failure */
goto mptctl_bus_reset_done;
}
if(ii <=0 && (ioctl->wait_done != 1 )) { if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
mpt_free_msg_frame(hd->ioc, mf); dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
ioctl->wait_done = 0; "TaskMgmt failed\n", ioc->name));
retval = -1; /* return failure */
goto mptctl_bus_reset_done;
}
pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, "
"iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, "
"term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus,
pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
le16_to_cpu(pScsiTmReply->IOCStatus),
le32_to_cpu(pScsiTmReply->IOCLogInfo),
pScsiTmReply->ResponseCode,
le32_to_cpu(pScsiTmReply->TerminationCount)));
iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED ||
iocstatus == MPI_IOCSTATUS_SUCCESS)
retval = 0;
else {
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"TaskMgmt failed\n", ioc->name));
retval = -1; /* return failure */ retval = -1; /* return failure */
} }
mptctl_bus_reset_done:
mptctl_free_tm_flags(ioctl->ioc); mptctl_bus_reset_done:
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
return retval; return retval;
} }
static int
mptctl_set_tm_flags(MPT_SCSI_HOST *hd) {
unsigned long flags;
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
if (hd->tmState == TM_STATE_NONE) {
hd->tmState = TM_STATE_IN_PROGRESS;
hd->tmPending = 1;
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
} else {
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
return -EBUSY;
}
return 0;
}
static void
mptctl_free_tm_flags(MPT_ADAPTER *ioc)
{
MPT_SCSI_HOST * hd;
unsigned long flags;
hd = shost_priv(ioc->sh);
if (hd == NULL)
return;
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmState = TM_STATE_NONE;
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* mptctl_ioc_reset /* mptctl_ioc_reset
@ -474,22 +503,23 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc)
static int static int
mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
{ {
MPT_IOCTL *ioctl = ioc->ioctl;
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC %s_reset routed to IOCTL driver!\n", ioc->name,
reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
if(ioctl == NULL)
return 1;
switch(reset_phase) { switch(reset_phase) {
case MPT_IOC_SETUP_RESET: case MPT_IOC_SETUP_RESET:
ioctl->status |= MPT_MGMT_STATUS_DID_IOCRESET; dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
break; "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
case MPT_IOC_POST_RESET:
ioctl->status &= ~MPT_MGMT_STATUS_DID_IOCRESET;
break; break;
case MPT_IOC_PRE_RESET: case MPT_IOC_PRE_RESET:
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
break;
case MPT_IOC_POST_RESET:
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) {
ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_DID_IOCRESET;
complete(&ioc->ioctl_cmds.done);
}
break;
default: default:
break; break;
} }
@ -643,7 +673,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
else else
ret = -EINVAL; ret = -EINVAL;
mutex_unlock(&iocp->ioctl->ioctl_mutex); mutex_unlock(&iocp->ioctl_cmds.mutex);
return ret; return ret;
} }
@ -759,6 +789,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
int sge_offset = 0; int sge_offset = 0;
u16 iocstat; u16 iocstat;
pFWDownloadReply_t ReplyMsg = NULL; pFWDownloadReply_t ReplyMsg = NULL;
unsigned long timeleft;
if (mpt_verify_adapter(ioc, &iocp) < 0) { if (mpt_verify_adapter(ioc, &iocp) < 0) {
printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n", printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
@ -893,16 +924,30 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
* Finally, perform firmware download. * Finally, perform firmware download.
*/ */
ReplyMsg = NULL; ReplyMsg = NULL;
SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, dlmsg->MsgContext);
INITIALIZE_MGMT_STATUS(iocp->ioctl_cmds.status)
mpt_put_msg_frame(mptctl_id, iocp, mf); mpt_put_msg_frame(mptctl_id, iocp, mf);
/* Now wait for the command to complete */ /* Now wait for the command to complete */
ret = wait_event_timeout(mptctl_wait, retry_wait:
iocp->ioctl->wait_done == 1, timeleft = wait_for_completion_timeout(&iocp->ioctl_cmds.done, HZ*60);
HZ*60); if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
ret = -ETIME;
printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
if (iocp->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
mpt_free_msg_frame(iocp, mf);
goto fwdl_out;
}
if (!timeleft)
mptctl_timeout_expired(iocp, mf);
else
goto retry_wait;
goto fwdl_out;
}
if(ret <=0 && (iocp->ioctl->wait_done != 1 )) { if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
/* Now we need to reset the board */ printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
mptctl_timeout_expired(iocp->ioctl); mpt_free_msg_frame(iocp, mf);
ret = -ENODATA; ret = -ENODATA;
goto fwdl_out; goto fwdl_out;
} }
@ -910,7 +955,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
if (sgl) if (sgl)
kfree_sgl(sgl, sgl_dma, buflist, iocp); kfree_sgl(sgl, sgl_dma, buflist, iocp);
ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame; ReplyMsg = (pFWDownloadReply_t)iocp->ioctl_cmds.reply;
iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK; iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
if (iocstat == MPI_IOCSTATUS_SUCCESS) { if (iocstat == MPI_IOCSTATUS_SUCCESS) {
printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name); printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name);
@ -934,6 +979,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
return 0; return 0;
fwdl_out: fwdl_out:
CLEAR_MGMT_STATUS(iocp->ioctl_cmds.status);
SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, 0);
kfree_sgl(sgl, sgl_dma, buflist, iocp); kfree_sgl(sgl, sgl_dma, buflist, iocp);
return ret; return ret;
} }
@ -1774,7 +1822,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
int msgContext; int msgContext;
u16 req_idx; u16 req_idx;
ulong timeout; ulong timeout;
unsigned long timeleft;
struct scsi_device *sdev; struct scsi_device *sdev;
unsigned long flags;
u8 function;
/* bufIn and bufOut are used for user to kernel space transfers /* bufIn and bufOut are used for user to kernel space transfers
*/ */
@ -1787,16 +1838,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
__FILE__, __LINE__, iocnum); __FILE__, __LINE__, iocnum);
return -ENODEV; return -ENODEV;
} }
if (!ioc->ioctl) {
spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
if (ioc->ioc_reset_in_progress) {
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - " printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
"No memory available during driver init.\n", "Busy with diagnostic reset\n", __FILE__, __LINE__);
__FILE__, __LINE__);
return -ENOMEM;
} else if (ioc->ioctl->status & MPT_MGMT_STATUS_DID_IOCRESET) {
printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
"Busy with IOC Reset \n", __FILE__, __LINE__);
return -EBUSY; return -EBUSY;
} }
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
/* Verify that the final request frame will not be too large. /* Verify that the final request frame will not be too large.
*/ */
@ -1830,10 +1880,12 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
"Unable to read MF from mpt_ioctl_command struct @ %p\n", "Unable to read MF from mpt_ioctl_command struct @ %p\n",
ioc->name, __FILE__, __LINE__, mfPtr); ioc->name, __FILE__, __LINE__, mfPtr);
function = -1;
rc = -EFAULT; rc = -EFAULT;
goto done_free_mem; goto done_free_mem;
} }
hdr->MsgContext = cpu_to_le32(msgContext); hdr->MsgContext = cpu_to_le32(msgContext);
function = hdr->Function;
/* Verify that this request is allowed. /* Verify that this request is allowed.
@ -1841,7 +1893,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sending mpi function (0x%02X), req=%p\n", dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sending mpi function (0x%02X), req=%p\n",
ioc->name, hdr->Function, mf)); ioc->name, hdr->Function, mf));
switch (hdr->Function) { switch (function) {
case MPI_FUNCTION_IOC_FACTS: case MPI_FUNCTION_IOC_FACTS:
case MPI_FUNCTION_PORT_FACTS: case MPI_FUNCTION_PORT_FACTS:
karg.dataOutSize = karg.dataInSize = 0; karg.dataOutSize = karg.dataInSize = 0;
@ -1938,8 +1990,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
pScsiReq->Control = cpu_to_le32(scsidir | qtag); pScsiReq->Control = cpu_to_le32(scsidir | qtag);
pScsiReq->DataLength = cpu_to_le32(dataSize); pScsiReq->DataLength = cpu_to_le32(dataSize);
ioc->ioctl->reset = MPTCTL_RESET_OK;
ioc->ioctl->id = pScsiReq->TargetID;
} else { } else {
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
@ -2017,8 +2067,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
pScsiReq->Control = cpu_to_le32(scsidir | qtag); pScsiReq->Control = cpu_to_le32(scsidir | qtag);
pScsiReq->DataLength = cpu_to_le32(dataSize); pScsiReq->DataLength = cpu_to_le32(dataSize);
ioc->ioctl->reset = MPTCTL_RESET_OK;
ioc->ioctl->id = pScsiReq->TargetID;
} else { } else {
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
"SCSI driver is not loaded. \n", "SCSI driver is not loaded. \n",
@ -2029,20 +2077,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
break; break;
case MPI_FUNCTION_SCSI_TASK_MGMT: case MPI_FUNCTION_SCSI_TASK_MGMT:
{ {
MPT_SCSI_HOST *hd = NULL; SCSITaskMgmt_t *pScsiTm;
if ((ioc->sh == NULL) || ((hd = shost_priv(ioc->sh)) == NULL)) { pScsiTm = (SCSITaskMgmt_t *)mf;
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"SCSI driver not loaded or SCSI host not found. \n", "\tTaskType=0x%x MsgFlags=0x%x "
ioc->name, __FILE__, __LINE__); "TaskMsgContext=0x%x id=%d channel=%d\n",
rc = -EFAULT; ioc->name, pScsiTm->TaskType, le32_to_cpu
goto done_free_mem; (pScsiTm->TaskMsgContext), pScsiTm->MsgFlags,
} else if (mptctl_set_tm_flags(hd) != 0) { pScsiTm->TargetID, pScsiTm->Bus));
rc = -EPERM;
goto done_free_mem;
}
}
break; break;
}
case MPI_FUNCTION_IOC_INIT: case MPI_FUNCTION_IOC_INIT:
{ {
@ -2186,9 +2231,16 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
ioc->add_sge(psge, flagsLength, (dma_addr_t) -1); ioc->add_sge(psge, flagsLength, (dma_addr_t) -1);
} }
ioc->ioctl->wait_done = 0; SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, hdr->MsgContext);
INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
mutex_lock(&ioc->taskmgmt_cmds.mutex);
if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
goto done_free_mem;
}
DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
@ -2199,10 +2251,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP); sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
if (rc != 0) { if (rc != 0) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"_send_handshake FAILED! (ioc %p, mf %p)\n", "send_handshake FAILED! (ioc %p, mf %p)\n",
ioc->name, ioc, mf)); ioc->name, ioc, mf));
mptctl_free_tm_flags(ioc); mpt_clear_taskmgmt_in_progress_flag(ioc);
rc = -ENODATA; rc = -ENODATA;
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
goto done_free_mem; goto done_free_mem;
} }
} }
@ -2212,36 +2265,47 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
/* Now wait for the command to complete */ /* Now wait for the command to complete */
timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
timeout = wait_event_timeout(mptctl_wait, retry_wait:
ioc->ioctl->wait_done == 1, timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
HZ*timeout); HZ*timeout);
if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) { rc = -ETIME;
/* Now we need to reset the board */ dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: TIMED OUT!\n",
ioc->name, __func__));
if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
mptctl_free_tm_flags(ioc); if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
mptctl_timeout_expired(ioc->ioctl); goto done_free_mem;
rc = -ENODATA; }
if (!timeleft) {
if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
mptctl_timeout_expired(ioc, mf);
mf = NULL;
} else
goto retry_wait;
goto done_free_mem; goto done_free_mem;
} }
if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
mf = NULL; mf = NULL;
/* If a valid reply frame, copy to the user. /* If a valid reply frame, copy to the user.
* Offset 2: reply length in U32's * Offset 2: reply length in U32's
*/ */
if (ioc->ioctl->status & MPT_MGMT_STATUS_RF_VALID) { if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
if (karg.maxReplyBytes < ioc->reply_sz) { if (karg.maxReplyBytes < ioc->reply_sz) {
sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]); sz = min(karg.maxReplyBytes,
4*ioc->ioctl_cmds.reply[2]);
} else { } else {
sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]); sz = min(ioc->reply_sz, 4*ioc->ioctl_cmds.reply[2]);
} }
if (sz > 0) { if (sz > 0) {
if (copy_to_user(karg.replyFrameBufPtr, if (copy_to_user(karg.replyFrameBufPtr,
&ioc->ioctl->ReplyFrame, sz)){ ioc->ioctl_cmds.reply, sz)){
printk(MYIOC_s_ERR_FMT printk(MYIOC_s_ERR_FMT
"%s@%d::mptctl_do_mpt_command - " "%s@%d::mptctl_do_mpt_command - "
"Unable to write out reply frame %p\n", "Unable to write out reply frame %p\n",
@ -2254,10 +2318,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
/* If valid sense data, copy to user. /* If valid sense data, copy to user.
*/ */
if (ioc->ioctl->status & MPT_MGMT_STATUS_SENSE_VALID) { if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_SENSE_VALID) {
sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
if (sz > 0) { if (sz > 0) {
if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) { if (copy_to_user(karg.senseDataPtr,
ioc->ioctl_cmds.sense, sz)) {
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
"Unable to write sense data to user %p\n", "Unable to write sense data to user %p\n",
ioc->name, __FILE__, __LINE__, ioc->name, __FILE__, __LINE__,
@ -2271,7 +2336,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
/* If the overall status is _GOOD and data in, copy data /* If the overall status is _GOOD and data in, copy data
* to user. * to user.
*/ */
if ((ioc->ioctl->status & MPT_MGMT_STATUS_COMMAND_GOOD) && if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD) &&
(karg.dataInSize > 0) && (bufIn.kptr)) { (karg.dataInSize > 0) && (bufIn.kptr)) {
if (copy_to_user(karg.dataInBufPtr, if (copy_to_user(karg.dataInBufPtr,
@ -2286,9 +2351,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
done_free_mem: done_free_mem:
ioc->ioctl->status &= ~(MPT_MGMT_STATUS_COMMAND_GOOD | CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
MPT_MGMT_STATUS_SENSE_VALID | SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
MPT_MGMT_STATUS_RF_VALID);
/* Free the allocated memory. /* Free the allocated memory.
*/ */
@ -2338,6 +2402,8 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
ToolboxIstwiReadWriteRequest_t *IstwiRWRequest; ToolboxIstwiReadWriteRequest_t *IstwiRWRequest;
MPT_FRAME_HDR *mf = NULL; MPT_FRAME_HDR *mf = NULL;
MPIHeader_t *mpi_hdr; MPIHeader_t *mpi_hdr;
unsigned long timeleft;
int retval;
/* Reset long to int. Should affect IA64 and SPARC only /* Reset long to int. Should affect IA64 and SPARC only
*/ */
@ -2478,8 +2544,8 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
* Gather ISTWI(Industry Standard Two Wire Interface) Data * Gather ISTWI(Industry Standard Two Wire Interface) Data
*/ */
if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
ioc->name,__func__)); "%s, no msg frames!!\n", ioc->name, __func__));
goto out; goto out;
} }
@ -2503,19 +2569,26 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
ioc->add_sge((char *)&IstwiRWRequest->SGL, ioc->add_sge((char *)&IstwiRWRequest->SGL,
(MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
ioc->ioctl->wait_done = 0; retval = 0;
SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
IstwiRWRequest->MsgContext);
INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
mpt_put_msg_frame(mptctl_id, ioc, mf); mpt_put_msg_frame(mptctl_id, ioc, mf);
rc = wait_event_timeout(mptctl_wait, retry_wait:
ioc->ioctl->wait_done == 1, timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */); HZ*MPT_IOCTL_DEFAULT_TIMEOUT);
if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
if(rc <=0 && (ioc->ioctl->wait_done != 1 )) { retval = -ETIME;
/* printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name, __func__);
* Now we need to reset the board if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
*/ mpt_free_msg_frame(ioc, mf);
mpt_free_msg_frame(ioc, mf); goto out;
mptctl_timeout_expired(ioc->ioctl); }
if (!timeleft)
mptctl_timeout_expired(ioc, mf);
else
goto retry_wait;
goto out; goto out;
} }
@ -2528,10 +2601,13 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
* bays have drives in them * bays have drives in them
* pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3) * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3)
*/ */
if (ioc->ioctl->status & MPT_MGMT_STATUS_RF_VALID) if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)
karg.rsvd = *(u32 *)pbuf; karg.rsvd = *(u32 *)pbuf;
out: out:
CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
if (pbuf) if (pbuf)
pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma); pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
@ -2755,7 +2831,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
mutex_unlock(&iocp->ioctl->ioctl_mutex); mutex_unlock(&iocp->ioctl_cmds.mutex);
return ret; return ret;
} }
@ -2809,7 +2885,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
*/ */
ret = mptctl_do_mpt_command (karg, &uarg->MF); ret = mptctl_do_mpt_command (karg, &uarg->MF);
mutex_unlock(&iocp->ioctl->ioctl_mutex); mutex_unlock(&iocp->ioctl_cmds.mutex);
return ret; return ret;
} }
@ -2861,21 +2937,10 @@ static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long a
static int static int
mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id) mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
MPT_IOCTL *mem;
MPT_ADAPTER *ioc = pci_get_drvdata(pdev); MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
/* mutex_init(&ioc->ioctl_cmds.mutex);
* Allocate and inite a MPT_IOCTL structure init_completion(&ioc->ioctl_cmds.done);
*/
mem = kzalloc(sizeof(MPT_IOCTL), GFP_KERNEL);
if (!mem) {
mptctl_remove(pdev);
return -ENOMEM;
}
ioc->ioctl = mem;
ioc->ioctl->ioc = ioc;
mutex_init(&ioc->ioctl->ioctl_mutex);
return 0; return 0;
} }
@ -2889,9 +2954,6 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static void static void
mptctl_remove(struct pci_dev *pdev) mptctl_remove(struct pci_dev *pdev)
{ {
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
kfree ( ioc->ioctl );
} }
static struct mpt_pci_driver mptctl_driver = { static struct mpt_pci_driver mptctl_driver = {
@ -2931,6 +2993,7 @@ static int __init mptctl_init(void)
goto out_fail; goto out_fail;
} }
mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER);
mpt_reset_register(mptctl_id, mptctl_ioc_reset); mpt_reset_register(mptctl_id, mptctl_ioc_reset);
mpt_event_register(mptctl_id, mptctl_event_process); mpt_event_register(mptctl_id, mptctl_event_process);
@ -2955,6 +3018,7 @@ static void mptctl_exit(void)
/* De-register callback handler from base module */ /* De-register callback handler from base module */
mpt_deregister(mptctl_id); mpt_deregister(mptctl_id);
mpt_reset_deregister(mptctl_taskmgmt_id);
mpt_device_driver_deregister(MPTCTL_DRIVER); mpt_device_driver_deregister(MPTCTL_DRIVER);

View File

@ -1290,8 +1290,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Clear the TM flags /* Clear the TM flags
*/ */
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
hd->abortSCpnt = NULL; hd->abortSCpnt = NULL;
/* Clear the pointer used to store /* Clear the pointer used to store

View File

@ -553,15 +553,21 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
{ {
MPT_FRAME_HDR *mf; MPT_FRAME_HDR *mf;
SCSITaskMgmt_t *pScsiTm; SCSITaskMgmt_t *pScsiTm;
if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
return 0;
mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc); mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
if (mf == NULL) { if (mf == NULL) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
"%s, no msg frames @%d!!\n", "%s, no msg frames @%d!!\n", ioc->name,
ioc->name, __func__, __LINE__)); __func__, __LINE__));
return 0; goto out_fail;
} }
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
ioc->name, mf));
/* Format the Request /* Format the Request
*/ */
pScsiTm = (SCSITaskMgmt_t *) mf; pScsiTm = (SCSITaskMgmt_t *) mf;
@ -574,9 +580,18 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf); mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
return 1; return 1;
out_fail:
mpt_clear_taskmgmt_in_progress_flag(ioc);
return 0;
} }
/** /**
@ -719,9 +734,12 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
if (!ev) { if (!ev) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
ioc->name,__func__, __LINE__)); ioc->name,__func__, __LINE__));
return 0; goto out_fail;
} }
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
ioc->name, mf));
INIT_WORK(&ev->work, mptsas_hotplug_work); INIT_WORK(&ev->work, mptsas_hotplug_work);
ev->ioc = ioc; ev->ioc = ioc;
ev->handle = le16_to_cpu(sas_event_data->DevHandle); ev->handle = le16_to_cpu(sas_event_data->DevHandle);
@ -734,10 +752,19 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sizeof(__le64)); sizeof(__le64));
ev->sas_address = le64_to_cpu(sas_address); ev->sas_address = le64_to_cpu(sas_address);
ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo); ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
ev->event_type = MPTSAS_DEL_DEVICE; ev->event_type = MPTSAS_DEL_DEVICE;
schedule_work(&ev->work); schedule_work(&ev->work);
kfree(target_reset_list); kfree(target_reset_list);
out_fail:
mpt_clear_taskmgmt_in_progress_flag(ioc);
return 0;
/* /*
* issue target reset to next device in the queue * issue target reset to next device in the queue
@ -3291,8 +3318,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Clear the TM flags /* Clear the TM flags
*/ */
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
hd->abortSCpnt = NULL; hd->abortSCpnt = NULL;
/* Clear the pointer used to store /* Clear the pointer used to store

View File

@ -1895,8 +1895,6 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
* NONE. * NONE.
*/ */
retval = 0; retval = 0;
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
} }
printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n", printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",

View File

@ -1474,8 +1474,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Clear the TM flags /* Clear the TM flags
*/ */
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
hd->abortSCpnt = NULL; hd->abortSCpnt = NULL;
/* Clear the pointer used to store /* Clear the pointer used to store