Commit 7e8c19ef authored by James Bottomley's avatar James Bottomley

mptfusion: delete watchdogs timers from mptctl and mptscsih

From: 	Moore, Eric Dean <Eric.Moore@lsil.com>

1) mptscsih.c: I have changed task management 
requests so they complete in same thread before returning
to os.  I removed the TMtimer code.  
 
(2) mptctl.c: I have deleted both TMtimer and timer code. Replaced
with wait_event_interruptible_timeout.  So commands are now
completed in same thread.  
 
(3) mptctl_do_fw_download - nasty polling of global parameters
that are set in contents of interrupt handler(mptctl_reply), now using
wait_event_interruptible_timeout. 
 
(4) I have cleaned up mptctl_reply.
Signed-off-by: default avatarEric Moore <Eric.Moore@lsil.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 71db3852
......@@ -83,8 +83,8 @@
#define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR
#endif
#define MPT_LINUX_VERSION_COMMON "3.01.18"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.18"
#define MPT_LINUX_VERSION_COMMON "3.01.19"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.19"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
......@@ -420,7 +420,6 @@ do { \
typedef struct _MPT_IOCTL {
struct _MPT_ADAPTER *ioc;
struct timer_list timer; /* timer function for this adapter */
u8 ReplyFrame[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
u8 sense[MPT_SENSE_BUFFER_ALLOC];
int wait_done; /* wake-up value for this ioc */
......@@ -428,8 +427,6 @@ typedef struct _MPT_IOCTL {
u8 status; /* current command status */
u8 reset; /* 1 if bus reset allowed */
u8 target; /* target for reset */
void *tmPtr;
struct timer_list TMtimer; /* timer function for this adapter */
struct semaphore sem_ioc;
} MPT_IOCTL;
......@@ -882,11 +879,9 @@ typedef struct _MPT_SCSI_HOST {
int port;
u32 pad0;
struct scsi_cmnd **ScsiLookup;
u32 qtag_tick;
VirtDevice **Targets;
MPT_LOCAL_REPLY *pLocal; /* used for internal commands */
struct timer_list timer;
struct timer_list TMtimer; /* Timer for TM commands ONLY */
/* Pool of memory for holding SCpnts before doing
* OS callbacks. freeQ is the free pool.
*/
......@@ -896,7 +891,6 @@ typedef struct _MPT_SCSI_HOST {
u8 pad1;
u8 tmState;
u8 rsvd[2];
MPT_FRAME_HDR *tmPtr; /* Ptr to TM request*/
MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */
struct scsi_cmnd *abortSCpnt;
MPT_LOCAL_REPLY localReply; /* internal cmd reply struct */
......
......@@ -81,6 +81,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h> /* for mdelay */
#include <linux/miscdevice.h>
#include <linux/smp_lock.h>
#include <linux/compat.h>
......@@ -145,7 +146,6 @@ static void mptctl_remove(struct pci_dev *);
#ifdef CONFIG_COMPAT
static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
#endif
/*
* Private function calls.
*/
......@@ -155,7 +155,7 @@ static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frag
struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
struct buflist *buflist, MPT_ADAPTER *ioc);
static void mptctl_timer_expired (unsigned long data);
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);
......@@ -188,9 +188,6 @@ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
#define MPT_IOCTL_DEFAULT_TIMEOUT 10 /* Default timeout value (seconds) */
static u32 fwReplyBuffer[16];
static pMPIDefaultReply_t ReplyMsg = NULL;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptctl_syscall_down - Down the MPT adapter syscall semaphore.
......@@ -208,11 +205,6 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
int rc = 0;
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
if (ioc->ioctl->tmPtr != NULL) {
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down BUSY\n"));
return -EBUSY;
}
if (nonblock) {
if (down_trylock(&ioc->ioctl->sem_ioc))
rc = -EAGAIN;
......@@ -239,56 +231,38 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
u16 iocStatus;
u8 cmd;
dctlprintk((MYIOC_s_INFO_FMT ": mptctl_reply()!\n", ioc->name));
dctlprintk(("mptctl_reply()!\n"));
if (req)
cmd = req->u.hdr.Function;
else
return 1;
if (ioc->ioctl) {
/* If timer is not running, then an error occurred.
* A timeout will call the reset routine to reload the messaging
* queues.
* Main callback will free message and reply frames.
*/
if (reply && (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) &&
(ioc->ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)) {
/* This is internally generated TM
*/
del_timer (&ioc->ioctl->TMtimer);
ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
mptctl_free_tm_flags(ioc);
if (reply==NULL) {
/* If TM failed, reset the timer on the existing command,
* will trigger an adapter reset.
*/
iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
if (iocStatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED) {
if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) {
dctlprintk(("mptctl_reply() NULL Reply "
"Function=%x!\n", cmd));
ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
del_timer (&ioc->ioctl->timer);
ioc->ioctl->timer.expires = jiffies + HZ;
add_timer(&ioc->ioctl->timer);
}
}
ioc->ioctl->tmPtr = NULL;
} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) {
/* Delete this timer
/* We are done, issue wake up
*/
del_timer (&ioc->ioctl->timer);
ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
ioc->ioctl->wait_done = 1;
wake_up (&mptctl_wait);
return 1;
}
dctlprintk(("mptctl_reply() with req=%p "
"reply=%p Function=%x!\n", req, reply, cmd));
/* Set the overall status byte. Good if:
* IOC status is good OR if no reply and a SCSI IO request
*/
if (reply) {
/* Copy the reply frame (which much exist
* for non-SCSI I/O) to the IOC structure.
*/
dctlprintk((MYIOC_s_INFO_FMT ": Copying Reply Frame @%p to IOC!\n",
ioc->name, reply));
dctlprintk(("Copying Reply Frame @%p to ioc%d!\n",
reply, ioc->id));
memcpy(ioc->ioctl->ReplyFrame, reply,
min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
......@@ -313,11 +287,14 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
/* Copy the sense data - if present
*/
if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
(reply->u.sreply.SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)){
(reply->u.sreply.SCSIState &
MPI_SCSI_STATE_AUTOSENSE_VALID)){
sz = req->u.scsireq.SenseBufferLength;
req_index = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
req_index =
le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
sense_data =
((u8 *)ioc->sense_buf_pool +
(req_index * MPT_SENSE_BUFFER_ALLOC));
memcpy(ioc->ioctl->sense, sense_data, sz);
ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
}
......@@ -325,45 +302,30 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
mptctl_free_tm_flags(ioc);
} else if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
(cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
}
/* We are done, issue wake up
*/
ioc->ioctl->wait_done = 1;
wake_up (&mptctl_wait);
} else if (reply && cmd == MPI_FUNCTION_FW_DOWNLOAD) {
/* Two paths to FW DOWNLOAD! */
// NOTE: Expects/requires non-Turbo reply!
dctlprintk((MYIOC_s_INFO_FMT ":Caching MPI_FUNCTION_FW_DOWNLOAD reply!\n",
ioc->name));
memcpy(fwReplyBuffer, reply, min_t(int, sizeof(fwReplyBuffer), 4*reply->u.reply.MsgLength));
ReplyMsg = (pMPIDefaultReply_t) fwReplyBuffer;
}
}
return 1;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* mptctl_timer_expired
/* mptctl_timeout_expired
*
* Call back for timer process. Used only for ioctl functionality.
* Expecting an interrupt, however timed out.
*
*/
static void mptctl_timer_expired (unsigned long data)
static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
{
MPT_IOCTL *ioctl = (MPT_IOCTL *) data;
int rc = 1;
dctlprintk((KERN_NOTICE MYNAM ": Timer Expired! Host %d\n",
dctlprintk((KERN_NOTICE MYNAM ": Timeout Expired! Host %d\n",
ioctl->ioc->id));
if (ioctl == NULL)
return;
ioctl->wait_done = 0;
if (ioctl->reset & MPTCTL_RESET_OK)
rc = mptctl_bus_reset(ioctl);
......@@ -371,6 +333,8 @@ static void mptctl_timer_expired (unsigned long data)
/* Issue a reset for this device.
* The IOC is not responding.
*/
dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
ioctl->ioc->name));
mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
}
return;
......@@ -435,26 +399,34 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
pScsiTm->Reserved2[ii] = 0;
pScsiTm->TaskMsgContext = 0;
dtmprintk((MYIOC_s_INFO_FMT "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
dtmprintk((MYIOC_s_INFO_FMT
"mptctl_bus_reset: issued.\n", ioctl->ioc->name));
ioctl->tmPtr = mf;
ioctl->TMtimer.expires = jiffies + HZ * 20; /* 20 seconds */
ioctl->status |= MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
add_timer(&ioctl->TMtimer);
DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, NO_SLEEP);
ioctl->wait_done=0;
if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
hd->ioc, mf));
goto mptctl_bus_reset_done;
}
if (retval != 0) {
dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
" (hd %p, ioc %p, mf %p) \n", ioctl->ioc->name, hd, hd->ioc, mf));
/* Now wait for the command to complete */
ii = wait_event_interruptible_timeout(mptctl_wait,
ioctl->wait_done == 1,
HZ*5 /* 5 second timeout */);
mptctl_free_tm_flags(ioctl->ioc);
del_timer(&ioctl->TMtimer);
mpt_free_msg_frame(ioctl->ioc, mf);
ioctl->tmPtr = NULL;
if(ii <=0 && (ioctl->wait_done != 1 )) {
ioctl->wait_done = 0;
retval = -1; /* return failure */
}
mptctl_bus_reset_done:
mpt_free_msg_frame(hd->ioc, mf);
mptctl_free_tm_flags(ioctl->ioc);
return retval;
}
......@@ -495,7 +467,6 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc)
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* mptctl_ioc_reset
*
......@@ -511,40 +482,19 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
if (reset_phase == MPT_IOC_SETUP_RESET){
;
} else if (reset_phase == MPT_IOC_PRE_RESET){
/* Someone has called the reset handler to
* do a hard reset. No more replies from the FW.
* Delete the timer. TM flags cleaned up by SCSI driver.
* Do not need to free msg frame, as re-initialized
*/
if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){
del_timer(&ioctl->timer);
}
if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){
ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
del_timer(&ioctl->TMtimer);
mpt_free_msg_frame(ioc, ioctl->tmPtr);
}
} else {
ioctl->tmPtr = NULL;
if(ioctl == NULL)
return 1;
/* Set the status and continue IOCTL
* processing. All memory will be free'd
* by originating thread after wake_up is
* called.
*/
if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){
switch(reset_phase) {
case MPT_IOC_SETUP_RESET:
ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
/* Wake up the calling process
*/
ioctl->wait_done = 1;
wake_up(&mptctl_wait);
}
break;
case MPT_IOC_POST_RESET:
ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET;
break;
case MPT_IOC_PRE_RESET:
default:
break;
}
return 1;
......@@ -749,9 +699,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
u32 nib;
int fw_bytes_copied = 0;
int i;
int cntdn;
int sge_offset = 0;
u16 iocstat;
pFWDownloadReply_t ReplyMsg = NULL;
dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
......@@ -882,31 +832,25 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
/*
* Finally, perform firmware download.
*/
ReplyMsg = NULL;
iocp->ioctl->wait_done = 0;
mpt_put_msg_frame(mptctl_id, iocp, mf);
/*
* Wait until the reply has been received
*/
for (cntdn=HZ*60, i=1; ReplyMsg == NULL; cntdn--, i++) {
if (!cntdn) {
ret = -ETIME;
goto fwdl_out;
}
/* Now wait for the command to complete */
ret = wait_event_interruptible_timeout(mptctl_wait,
iocp->ioctl->wait_done == 1,
HZ*60);
if (!(i%HZ)) {
dctlprintk((KERN_INFO "DbG::_do_fwdl: "
"In ReplyMsg loop - iteration %d\n",
i));
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
if(ret <=0 && (iocp->ioctl->wait_done != 1 )) {
/* Now we need to reset the board */
mptctl_timeout_expired(iocp->ioctl);
ret = -ENODATA;
goto fwdl_out;
}
if (sgl)
kfree_sgl(sgl, sgl_dma, buflist, iocp);
ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
if (iocstat == MPI_IOCSTATUS_SUCCESS) {
printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name);
......@@ -1826,8 +1770,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
int iocnum, flagsLength;
int sz, rc = 0;
int msgContext;
int tm_flags_set = 0;
u16 req_idx;
ulong timeout;
dctlprintk(("mptctl_do_mpt_command called.\n"));
bufIn.kptr = bufOut.kptr = NULL;
......@@ -2043,7 +1987,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
rc = -EPERM;
goto done_free_mem;
}
tm_flags_set = 1;
}
break;
......@@ -2195,65 +2138,44 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
}
/* The request is complete. Set the timer parameters
* and issue the request.
*/
if (karg.timeout > 0) {
ioc->ioctl->timer.expires = jiffies + HZ*karg.timeout;
} else {
ioc->ioctl->timer.expires = jiffies + HZ*MPT_IOCTL_DEFAULT_TIMEOUT;
}
ioc->ioctl->wait_done = 0;
ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;
add_timer(&ioc->ioctl->timer);
if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
rc = mpt_send_handshake_request(mptctl_id, ioc,
sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
if (rc == 0) {
wait_event(mptctl_wait, ioc->ioctl->wait_done);
} else {
if (mpt_send_handshake_request(mptctl_id, ioc,
sizeof(SCSITaskMgmt_t), (u32*)mf,
CAN_SLEEP) != 0) {
dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
" (ioc %p, mf %p) \n", ioc->name,
ioc, mf));
mptctl_free_tm_flags(ioc);
tm_flags_set= 0;
del_timer(&ioc->ioctl->timer);
ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;
mpt_free_msg_frame(ioc, mf);
rc = -ENODATA;
goto done_free_mem;
}
} else {
} else
mpt_put_msg_frame(mptctl_id, ioc, mf);
wait_event(mptctl_wait, ioc->ioctl->wait_done);
/* Now wait for the command to complete */
timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
timeout = wait_event_interruptible_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;
goto done_free_mem;
}
mf = NULL;
/* MF Cleanup:
* If command failed and failure triggered a diagnostic reset
* OR a diagnostic reset happens during command processing,
* no data, messaging queues are reset (mf cannot be accessed),
* and status is DID_IOCRESET
*
* If a user-requested bus reset fails to be handshaked, then
* mf is returned to free queue and status is TM_FAILED.
*
* Otherise, the command completed and the mf was freed
# by ISR (mf cannot be touched).
*/
if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
/* The timer callback deleted the
* timer and reset the adapter queues.
*/
printk(KERN_WARNING "%s@%d::mptctl_do_mpt_command - "
"Timeout Occurred on IOCTL! Reset IOC.\n", __FILE__, __LINE__);
tm_flags_set= 0;
rc = -ETIME;
} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TM_FAILED) {
/* User TM request failed! mf has not been freed.
*/
rc = -ENODATA;
} else {
/* If a valid reply frame, copy to the user.
* Offset 2: reply length in U32's
*/
......@@ -2267,8 +2189,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
if (sz > 0) {
if (copy_to_user(karg.replyFrameBufPtr,
&ioc->ioctl->ReplyFrame, sz)){
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
printk(KERN_ERR
"%s@%d::mptctl_do_mpt_command - "
"Unable to write out reply frame %p\n",
__FILE__, __LINE__, karg.replyFrameBufPtr);
rc = -ENODATA;
......@@ -2308,19 +2230,12 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
rc = -ENODATA;
}
}
}
done_free_mem:
/* Clear all status bits except TMTIMER_ACTIVE, this bit is cleared
* upon completion of the TM command.
* ioc->ioctl->status = 0;
*/
ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TIMER_ACTIVE | MPT_IOCTL_STATUS_TM_FAILED |
MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
MPT_IOCTL_STATUS_RF_VALID | MPT_IOCTL_STATUS_DID_IOCRESET);
if (tm_flags_set)
mptctl_free_tm_flags(ioc);
ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |
MPT_IOCTL_STATUS_SENSE_VALID |
MPT_IOCTL_STATUS_RF_VALID );
/* Free the allocated memory.
*/
......@@ -2701,14 +2616,6 @@ static struct miscdevice mptctl_miscdev = {
#include <linux/ioctl32.h>
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* compat_XXX functions are used to provide a conversion between
* pointers and u32's. If the arg does not contain any pointers, then
* a specialized function (compat_XXX) is not needed. If the arg
* does contain pointer(s), then the specialized function is used
* to ensure the structure contents is properly processed by mptctl.
*/
static int
compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
......@@ -2804,7 +2711,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
int ret;
long ret;
lock_kernel();
switch (cmd) {
case MPTIOCINFO:
......@@ -2867,12 +2774,6 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
memset(mem, 0, sz);
ioc->ioctl = (MPT_IOCTL *) mem;
ioc->ioctl->ioc = ioc;
init_timer (&ioc->ioctl->timer);
ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
ioc->ioctl->timer.function = mptctl_timer_expired;
init_timer (&ioc->ioctl->TMtimer);
ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
ioc->ioctl->TMtimer.function = mptctl_timer_expired;
sema_init(&ioc->ioctl->sem_ioc, 1);
return 0;
......@@ -2916,7 +2817,6 @@ static int __init mptctl_init(void)
": failed to register dd callbacks\n"));
}
/* Register this device */
err = misc_register(&mptctl_miscdev);
if (err < 0) {
......@@ -2948,7 +2848,6 @@ static int __init mptctl_init(void)
out_fail:
mpt_device_driver_deregister(MPTCTL_DRIVER);
return err;
......
......@@ -179,10 +179,11 @@ static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
static void copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
......@@ -196,13 +197,9 @@ static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int fl
static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static void mptscsih_timer_expired(unsigned long data);
static void mptscsih_taskmgmt_timeout(unsigned long data);
static void mptscsih_schedule_reset(void *hd);
static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
static struct work_struct mptscsih_rstTask;
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
static void mptscsih_domainValidation(void *hd);
......@@ -1207,7 +1204,6 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->tmState = TM_STATE_NONE;
hd->resetPending = 0;
hd->abortSCpnt = NULL;
hd->tmPtr = NULL;
/* Clear the pointer used to store
* single-threaded commands, i.e., those
......@@ -1224,14 +1220,6 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->timer.data = (unsigned long) hd;
hd->timer.function = mptscsih_timer_expired;
init_timer(&hd->TMtimer);
hd->TMtimer.data = (unsigned long) hd;
hd->TMtimer.function = mptscsih_taskmgmt_timeout;
hd->qtag_tick = jiffies;
/* Moved Earlier Pam D */
/* ioc->sh = sh; */
if (ioc->bus_type == SCSI) {
/* Update with the driver setup
* values.
......@@ -1925,7 +1913,6 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
* @target: Logical Target ID for reset (if appropriate)
* @lun: Logical Unit for reset (if appropriate)
* @ctx2abort: Context for the task to be aborted (if appropriate)
* @sleepFlag: If set, use udelay instead of schedule in handshake code.
*
* Remark: Currently invoked from a non-interrupt thread (_bh).
*
......@@ -1935,7 +1922,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
* Returns 0 for SUCCESS or -1 if FAILED.
*/
static int
mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
{
MPT_ADAPTER *ioc;
int rc = -1;
......@@ -2015,7 +2002,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
*/
if (hd->hard_resets < -1)
hd->hard_resets++;
rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag);
rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
if (rc) {
printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
} else {
......@@ -2029,7 +2016,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
hd->ioc->name));
rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
}
dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
......@@ -2046,7 +2033,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
* @target: Logical Target ID for reset (if appropriate)
* @lun: Logical Unit for reset (if appropriate)
* @ctx2abort: Context for the task to be aborted (if appropriate)
* @sleepFlag: If set, use udelay instead of schedule in handshake code.
*
* Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
* or a non-interrupt thread. In the former, must not call schedule().
......@@ -2057,7 +2043,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
* else other non-zero value returned.
*/
static int
mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
{
MPT_FRAME_HDR *mf;
SCSITaskMgmt_t *pScsiTm;
......@@ -2099,27 +2085,30 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
pScsiTm->TaskMsgContext = ctx2abort;
/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
mpt_put_msg_frame(hd->ioc->id, mf);
* Save the MF pointer in case the request times out.
*/
hd->tmPtr = mf;
hd->TMtimer.expires = jiffies + timeout;
add_timer(&hd->TMtimer);
dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
dtmprintk((MYIOC_s_INFO_FMT
"IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
hd->ioc->name, ctx2abort, type));
DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc,
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
!= 0) {
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
CAN_SLEEP)) != 0) {
dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
hd->tmPtr = NULL;
del_timer(&hd->TMtimer);
" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
hd->ioc, mf));
mpt_free_msg_frame(hd->ioc, mf);
return retval;
}
if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
hd->ioc, mf));
mpt_free_msg_frame(hd->ioc, mf);
dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
hd->ioc->name));
retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
}
return retval;
......@@ -2193,7 +2182,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
ctx2abort, 2 /* 2 second timeout */)
< 0) {
/* The TM request failed and the subsequent FW-reload failed!
......@@ -2226,7 +2215,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
}
spin_lock_irq(host_lock);
return SUCCESS;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......@@ -2259,15 +2247,10 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
hd->ioc->name, SCpnt);
/* Supported for FC only.
*/
if (hd->ioc->bus_type == SCSI)
return FAILED;
spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
SCpnt->device->channel, SCpnt->device->id,
0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
0, 0, 5 /* 5 second timeout */)
< 0){
/* The TM request failed and the subsequent FW-reload failed!
* Fatal error case.
......@@ -2317,7 +2300,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
/* We are now ready to execute the task management request. */
spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
< 0){
/* The TM request failed and the subsequent FW-reload failed!
......@@ -2398,7 +2381,7 @@ static int
mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
{
unsigned long flags;
int loop_count = 10 * 4; /* Wait 10 seconds */
int loop_count = 4 * 10; /* Wait 10 seconds */
int status = FAILED;
do {
......@@ -2406,8 +2389,8 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
if (hd->tmState == TM_STATE_NONE) {
hd->tmState = TM_STATE_IN_PROGRESS;
hd->tmPending = 1;
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
status = SUCCESS;
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
break;
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
......@@ -2417,6 +2400,34 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
return status;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_tm_wait_for_completion - wait for completion of TM task
* @hd: Pointer to MPT host structure.
*
* Returns {SUCCESS,FAILED}.
*/
static int
mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
{
unsigned long flags;
int loop_count = 4 * timeout;
int status = FAILED;
do {
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
if(hd->tmPending == 0) {
status = SUCCESS;
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
break;
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
msleep_interruptible(250);
} while (--loop_count);
return status;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
......@@ -2449,9 +2460,6 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
* Decrement count of outstanding TM requests.
*/
hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
if (hd->tmPtr) {
del_timer(&hd->TMtimer);
}
} else {
dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
ioc->name));
......@@ -2505,7 +2513,6 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
}
}
hd->tmPtr = NULL;
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
......@@ -2913,14 +2920,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
mpt_free_msg_frame(ioc, hd->cmdPtr);
}
/* 2d. If a task management has not completed,
* free resources associated with this request.
*/
if (hd->tmPtr) {
del_timer(&hd->TMtimer);
mpt_free_msg_frame(ioc, hd->tmPtr);
}
dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
} else {
......@@ -2942,12 +2941,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
/* 2. Chain Buffer initialization
*/
/* 3. tmPtr clear
*/
if (hd->tmPtr) {
hd->tmPtr = NULL;
}
/* 4. Renegotiate to all devices, if SCSI
*/
if (ioc->bus_type == SCSI) {
......@@ -3810,60 +3803,6 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* mptscsih_taskmgmt_timeout - Call back for timeout on a
* task management request.
* @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
*
*/
static void mptscsih_taskmgmt_timeout(unsigned long data)
{
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
"TM request timed out!\n", hd->ioc->name));
/* Delete the timer that triggered this callback.
* Remark: del_timer checks to make sure timer is active
* before deleting.
*/
del_timer(&hd->TMtimer);
/* Call the reset handler. Already had a TM request
* timeout - so issue a diagnostic reset
*/
INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
schedule_work(&mptscsih_rstTask);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* mptscsih_schedule_reset - Call back for timeout on a
* task management request.
* @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
*
*/
static void
mptscsih_schedule_reset(void *arg)
{
MPT_SCSI_HOST *hd;
hd = (MPT_SCSI_HOST *) arg;
if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
} else {
/* Because we have reset the IOC, no TM requests can be
* pending. So let's make sure the tmPending flag is reset.
*/
dtmprintk((KERN_WARNING MYNAM
": %s: mptscsih_taskmgmt_timeout\n",
hd->ioc->name));
hd->tmPending = 0;
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Bus Scan and Domain Validation functionality ...
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment