|
@@ -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_IOCTL *ioctl);
|
|
|
|
-static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd);
|
|
|
|
-static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
|
|
|
|
|
|
+static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function);
|
|
|
|
|
|
/*
|
|
/*
|
|
* 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;
|
|
|
|
- int sz, req_index;
|
|
|
|
- u16 iocStatus;
|
|
|
|
- u8 cmd;
|
|
|
|
|
|
+ char *sense_data;
|
|
|
|
+ int req_index;
|
|
|
|
+ int sz;
|
|
|
|
|
|
- if (req)
|
|
|
|
- cmd = req->u.hdr.Function;
|
|
|
|
- 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) {
|
|
|
|
-
|
|
|
|
- if (reply==NULL) {
|
|
|
|
-
|
|
|
|
- dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_reply() NULL Reply "
|
|
|
|
- "Function=%x!\n", ioc->name, cmd));
|
|
|
|
|
|
+ if (!req)
|
|
|
|
+ return 0;
|
|
|
|
|
|
- ioc->ioctl->status |= MPT_MGMT_STATUS_COMMAND_GOOD;
|
|
|
|
- ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
|
|
|
|
|
|
+ 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));
|
|
|
|
|
|
- /* We are done, issue wake up
|
|
|
|
- */
|
|
|
|
- ioc->ioctl->wait_done = 1;
|
|
|
|
- wake_up (&mptctl_wait);
|
|
|
|
- return 1;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * 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;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
|
|
|
|
|
|
- /* Copy the reply frame (which much exist
|
|
|
|
- * for non-SCSI I/O) to the IOC structure.
|
|
|
|
- */
|
|
|
|
- memcpy(ioc->ioctl->ReplyFrame, reply,
|
|
|
|
- min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
|
|
|
|
- ioc->ioctl->status |= MPT_MGMT_STATUS_RF_VALID;
|
|
|
|
|
|
+ if (!reply)
|
|
|
|
+ goto out;
|
|
|
|
|
|
- /* Set the command status to GOOD if IOC Status is GOOD
|
|
|
|
- * OR if SCSI I/O cmd and data underrun or recovered error.
|
|
|
|
- */
|
|
|
|
- iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
|
|
|
|
- if (iocStatus == MPI_IOCSTATUS_SUCCESS)
|
|
|
|
- ioc->ioctl->status |= MPT_MGMT_STATUS_COMMAND_GOOD;
|
|
|
|
-
|
|
|
|
- if (iocStatus || reply->u.reply.IOCLogInfo)
|
|
|
|
- dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tiocstatus (0x%04X), "
|
|
|
|
- "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;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
|
|
|
|
+ sz = min(ioc->reply_sz, 4*reply->u.reply.MsgLength);
|
|
|
|
+ memcpy(ioc->ioctl_cmds.reply, reply, sz);
|
|
|
|
|
|
- /* Copy the sense data - if present
|
|
|
|
- */
|
|
|
|
- if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
|
|
|
|
- (reply->u.sreply.SCSIState &
|
|
|
|
- MPI_SCSI_STATE_AUTOSENSE_VALID)){
|
|
|
|
|
|
+ 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)));
|
|
|
|
+
|
|
|
|
+ if ((req->u.hdr.Function == MPI_FUNCTION_SCSI_IO_REQUEST) ||
|
|
|
|
+ (req->u.hdr.Function ==
|
|
|
|
+ MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
|
|
|
|
+
|
|
|
|
+ if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState)
|
|
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
|
|
+ "scsi_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)));
|
|
|
|
+
|
|
|
|
+ if (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 =
|
|
|
|
- ((u8 *)ioc->sense_buf_pool +
|
|
|
|
|
|
+ sense_data = ((u8 *)ioc->sense_buf_pool +
|
|
(req_index * MPT_SENSE_BUFFER_ALLOC));
|
|
(req_index * MPT_SENSE_BUFFER_ALLOC));
|
|
- memcpy(ioc->ioctl->sense, sense_data, sz);
|
|
|
|
- ioc->ioctl->status |= MPT_MGMT_STATUS_SENSE_VALID;
|
|
|
|
|
|
+ memcpy(ioc->ioctl_cmds.sense, sense_data, sz);
|
|
|
|
+ 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)
|
|
|
|
- return;
|
|
|
|
- dctlprintk(ioctl->ioc,
|
|
|
|
- printk(MYIOC_s_DEBUG_FMT ": Timeout Expired! Host %d\n",
|
|
|
|
- ioctl->ioc->name, ioctl->ioc->id));
|
|
|
|
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n",
|
|
|
|
+ ioc->name, __func__));
|
|
|
|
|
|
- ioctl->wait_done = 0;
|
|
|
|
- if (ioctl->reset & MPTCTL_RESET_OK)
|
|
|
|
- rc = mptctl_bus_reset(ioctl);
|
|
|
|
|
|
+ if (mpt_fwfault_debug)
|
|
|
|
+ mpt_halt_firmware(ioc);
|
|
|
|
|
|
- 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);
|
|
|
|
|
|
+ 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;
|
|
|
|
|
|
+ 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;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- ioctl->reset &= ~MPTCTL_RESET_OK;
|
|
|
|
-
|
|
|
|
- if (ioctl->ioc->sh == NULL)
|
|
|
|
|
|
+ int retval;
|
|
|
|
+ unsigned long timeout;
|
|
|
|
+ unsigned long time_count;
|
|
|
|
+ u16 iocstatus;
|
|
|
|
+
|
|
|
|
+ /* bus reset is only good for SCSI IO, RAID PASSTHRU */
|
|
|
|
+ if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) ||
|
|
|
|
+ (function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
|
|
|
|
+ dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
|
|
|
|
+ "TaskMgmt, not SCSI_IO!!\n", ioc->name));
|
|
return -EPERM;
|
|
return -EPERM;
|
|
|
|
+ }
|
|
|
|
|
|
- hd = shost_priv(ioctl->ioc->sh);
|
|
|
|
- if (hd == NULL)
|
|
|
|
|
|
+ mutex_lock(&ioc->taskmgmt_cmds.mutex);
|
|
|
|
+ if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
|
|
|
|
+ mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
return -EPERM;
|
|
return -EPERM;
|
|
|
|
+ }
|
|
|
|
|
|
- /* Single threading ....
|
|
|
|
- */
|
|
|
|
- if (mptctl_set_tm_flags(hd) != 0)
|
|
|
|
- return -EPERM;
|
|
|
|
|
|
+ retval = 0;
|
|
|
|
|
|
/* Send request
|
|
/* Send request
|
|
*/
|
|
*/
|
|
- if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) {
|
|
|
|
- dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt, no msg frames!!\n",
|
|
|
|
- ioctl->ioc->name));
|
|
|
|
-
|
|
|
|
- mptctl_free_tm_flags(ioctl->ioc);
|
|
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc);
|
|
|
|
+ if (mf == NULL) {
|
|
|
|
+ dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
|
|
|
|
+ "TaskMgmt, no msg frames!!\n", ioc->name));
|
|
|
|
+ mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
|
|
+ retval = -ENOMEM;
|
|
|
|
+ goto mptctl_bus_reset_done;
|
|
}
|
|
}
|
|
|
|
|
|
- dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
|
|
|
|
- ioctl->ioc->name, mf));
|
|
|
|
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
|
|
|
|
+ ioc->name, mf));
|
|
|
|
|
|
pScsiTm = (SCSITaskMgmt_t *) mf;
|
|
pScsiTm = (SCSITaskMgmt_t *) mf;
|
|
- pScsiTm->TargetID = ioctl->id;
|
|
|
|
- pScsiTm->Bus = hd->port; /* 0 */
|
|
|
|
- pScsiTm->ChainOffset = 0;
|
|
|
|
|
|
+ memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
|
|
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;
|
|
|
|
- dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT
|
|
|
|
- "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
|
|
|
|
-
|
|
|
|
- DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf);
|
|
|
|
|
|
+ switch (ioc->bus_type) {
|
|
|
|
+ case FC:
|
|
|
|
+ timeout = 40;
|
|
|
|
+ break;
|
|
|
|
+ case SAS:
|
|
|
|
+ timeout = 30;
|
|
|
|
+ break;
|
|
|
|
+ case SPI:
|
|
|
|
+ default:
|
|
|
|
+ timeout = 2;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
- ioctl->wait_done=0;
|
|
|
|
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
|
|
+ "TaskMgmt type=%d timeout=%ld\n",
|
|
|
|
+ ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout));
|
|
|
|
|
|
- if ((ioctl->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
|
|
|
|
- (ioctl->ioc->facts.MsgVersion >= MPI_VERSION_01_05))
|
|
|
|
- mpt_put_msg_frame_hi_pri(mptctl_id, ioctl->ioc, mf);
|
|
|
|
|
|
+ INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
|
|
+ CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
|
|
+ time_count = jiffies;
|
|
|
|
+ if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
|
|
|
|
+ (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,
|
|
|
|
- sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
|
|
|
|
|
|
+ retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc,
|
|
|
|
+ sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP);
|
|
if (retval != 0) {
|
|
if (retval != 0) {
|
|
- dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!"
|
|
|
|
- " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
|
|
|
|
- hd->ioc, mf));
|
|
|
|
|
|
+ dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
|
|
|
|
+ "TaskMgmt send_handshake FAILED!"
|
|
|
|
+ " (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,
|
|
|
|
- ioctl->wait_done == 1,
|
|
|
|
- HZ*5 /* 5 second timeout */);
|
|
|
|
|
|
+ ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
|
|
|
|
+ if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
|
|
+ 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 )) {
|
|
|
|
- mpt_free_msg_frame(hd->ioc, mf);
|
|
|
|
- ioctl->wait_done = 0;
|
|
|
|
|
|
+ if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
|
|
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
|
|
+ "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
|
|
|
|
+ "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
|
|
|
|
+ break;
|
|
|
|
+ case MPT_IOC_PRE_RESET:
|
|
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
|
|
+ "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
|
|
break;
|
|
break;
|
|
case MPT_IOC_POST_RESET:
|
|
case MPT_IOC_POST_RESET:
|
|
- ioctl->status &= ~MPT_MGMT_STATUS_DID_IOCRESET;
|
|
|
|
|
|
+ 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;
|
|
break;
|
|
- case MPT_IOC_PRE_RESET:
|
|
|
|
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,
|
|
|
|
- iocp->ioctl->wait_done == 1,
|
|
|
|
- HZ*60);
|
|
|
|
|
|
+retry_wait:
|
|
|
|
+ timeleft = wait_for_completion_timeout(&iocp->ioctl_cmds.done, 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 )) {
|
|
|
|
- /* Now we need to reset the board */
|
|
|
|
- mptctl_timeout_expired(iocp->ioctl);
|
|
|
|
|
|
+ if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
|
|
|
|
+ printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
|
|
|
|
+ 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) {
|
|
|
|
- printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
|
|
|
|
- "No memory available during driver init.\n",
|
|
|
|
- __FILE__, __LINE__);
|
|
|
|
- return -ENOMEM;
|
|
|
|
- } else if (ioc->ioctl->status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
|
|
|
|
+
|
|
|
|
+ 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 - "
|
|
- "Busy with IOC Reset \n", __FILE__, __LINE__);
|
|
|
|
|
|
+ "Busy with diagnostic 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;
|
|
|
|
- if ((ioc->sh == NULL) || ((hd = shost_priv(ioc->sh)) == NULL)) {
|
|
|
|
- printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
|
|
|
|
- "SCSI driver not loaded or SCSI host not found. \n",
|
|
|
|
- ioc->name, __FILE__, __LINE__);
|
|
|
|
- rc = -EFAULT;
|
|
|
|
- goto done_free_mem;
|
|
|
|
- } else if (mptctl_set_tm_flags(hd) != 0) {
|
|
|
|
- rc = -EPERM;
|
|
|
|
- goto done_free_mem;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ {
|
|
|
|
+ SCSITaskMgmt_t *pScsiTm;
|
|
|
|
+ pScsiTm = (SCSITaskMgmt_t *)mf;
|
|
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
|
|
+ "\tTaskType=0x%x MsgFlags=0x%x "
|
|
|
|
+ "TaskMsgContext=0x%x id=%d channel=%d\n",
|
|
|
|
+ ioc->name, pScsiTm->TaskType, le32_to_cpu
|
|
|
|
+ (pScsiTm->TaskMsgContext), pScsiTm->MsgFlags,
|
|
|
|
+ pScsiTm->TargetID, pScsiTm->Bus));
|
|
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,
|
|
|
|
- ioc->ioctl->wait_done == 1,
|
|
|
|
- HZ*timeout);
|
|
|
|
-
|
|
|
|
- if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
|
|
|
|
- /* Now we need to reset the board */
|
|
|
|
-
|
|
|
|
- if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)
|
|
|
|
- mptctl_free_tm_flags(ioc);
|
|
|
|
-
|
|
|
|
- mptctl_timeout_expired(ioc->ioctl);
|
|
|
|
- rc = -ENODATA;
|
|
|
|
|
|
+retry_wait:
|
|
|
|
+ timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
|
|
|
|
+ HZ*timeout);
|
|
|
|
+ if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
|
|
+ rc = -ETIME;
|
|
|
|
+ dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: TIMED OUT!\n",
|
|
|
|
+ ioc->name, __func__));
|
|
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
|
|
+ if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
|
|
|
|
+ mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
|
|
+ goto done_free_mem;
|
|
|
|
+ }
|
|
|
|
+ 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 |
|
|
|
|
- MPT_MGMT_STATUS_SENSE_VALID |
|
|
|
|
- MPT_MGMT_STATUS_RF_VALID);
|
|
|
|
|
|
+ CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
|
|
|
|
|
|
/* 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",
|
|
|
|
- ioc->name,__func__));
|
|
|
|
|
|
+ dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
|
|
|
|
+ "%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,
|
|
|
|
- ioc->ioctl->wait_done == 1,
|
|
|
|
- HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
|
|
|
|
-
|
|
|
|
- if(rc <=0 && (ioc->ioctl->wait_done != 1 )) {
|
|
|
|
- /*
|
|
|
|
- * Now we need to reset the board
|
|
|
|
- */
|
|
|
|
- mpt_free_msg_frame(ioc, mf);
|
|
|
|
- mptctl_timeout_expired(ioc->ioctl);
|
|
|
|
|
|
+retry_wait:
|
|
|
|
+ timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
|
|
|
|
+ HZ*MPT_IOCTL_DEFAULT_TIMEOUT);
|
|
|
|
+ if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
|
|
+ retval = -ETIME;
|
|
|
|
+ printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name, __func__);
|
|
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ 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);
|
|
|
|
|
|
- /*
|
|
|
|
- * Allocate and inite a MPT_IOCTL structure
|
|
|
|
- */
|
|
|
|
- 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);
|
|
|
|
|
|
+ mutex_init(&ioc->ioctl_cmds.mutex);
|
|
|
|
+ init_completion(&ioc->ioctl_cmds.done);
|
|
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);
|
|
|
|
|