From 65c054f235fda2d545ecd2a7948906a3cf0c1f39 Mon Sep 17 00:00:00 2001 From: Kei Tokunaga Date: Mon, 15 Mar 2010 14:48:43 +0900 Subject: [SCSI] mpt: modify mptctl_exit() to call proper deregister functions This patch fixes some issues of mptctl_exit(). 1) It doesn't call mpt_deregister() for mptctl_taskmgmt_id => Insmoding/rmmoding mptctl.ko repeadtedly (up to MPT_MAX_PROTOCOL_DRIVERS-1 at most) can eat up all cb_idx, and that would cause a lack of MptCallbacks[], MptDriverClass[], and MptEvHandlers[]. 2) It doesn't call mpt_event_deregister() for mptctl_id => Need to call it. 3) It calls mpt_reset_deregister() for mptctl_taskmgmt_id => This could accidentally deregister an innocent reset handler that you don't want to. This patch also adds a check for mptctl_taskmgmt_id. Signed-off-by: Kei Tokunaga Acked-by: "Desai, Kashyap" Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index caa8f568a41..80421d2cf04 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -2991,6 +2991,14 @@ static int __init mptctl_init(void) } mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER); + if (!mptctl_taskmgmt_id || mptctl_taskmgmt_id >= MPT_MAX_PROTOCOL_DRIVERS) { + printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n"); + mpt_deregister(mptctl_id); + misc_deregister(&mptctl_miscdev); + err = -EBUSY; + goto out_fail; + } + mpt_reset_register(mptctl_id, mptctl_ioc_reset); mpt_event_register(mptctl_id, mptctl_event_process); @@ -3010,12 +3018,15 @@ static void mptctl_exit(void) printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n", mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor); + /* De-register event handler from base module */ + mpt_event_deregister(mptctl_id); + /* De-register reset handler from base module */ mpt_reset_deregister(mptctl_id); /* De-register callback handler from base module */ + mpt_deregister(mptctl_taskmgmt_id); mpt_deregister(mptctl_id); - mpt_reset_deregister(mptctl_taskmgmt_id); mpt_device_driver_deregister(MPTCTL_DRIVER); -- cgit v1.2.3-70-g09d2 From d0f698c46141e1d179fb3a86a0ae668d2fd12916 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:12:17 +0530 Subject: [SCSI] mptfusion: Added new less expensive RESET (Message Unit Reset) Message Unit Reset - instructs the IOC to reset the Reply Post and Free FIFO's. All the Message Frames on Reply Free FIFO are discarded. All posted buffers are freed, and event notification is turned off. IOC doesnt reply to any outstanding request. This will transfer IOC to READY state. Message unit ready is less expensive operations than Hard Reset. soft reset will not force Firmware to reload again, it only do clean up of Message units. mpt_Soft_Hard_ResetHandler will first try for Soft Reset,if it fails then go for big hammer reset which is Hard Reset. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 170 +++++++++++++++++++++++++++++++++++++- drivers/message/fusion/mptbase.h | 1 + drivers/message/fusion/mptctl.c | 2 +- drivers/message/fusion/mptsas.c | 8 +- drivers/message/fusion/mptscsih.c | 6 +- 5 files changed, 177 insertions(+), 10 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5382b5a44af..a4f023bd5d2 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -5064,7 +5064,7 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) if (!timeleft) { printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n", ioc->name, __func__); - mpt_HardResetHandler(ioc, CAN_SLEEP); + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); mpt_free_msg_frame(ioc, mf); } goto out; @@ -6456,7 +6456,7 @@ out: issue_hard_reset = 0; printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", ioc->name, __func__); - mpt_HardResetHandler(ioc, CAN_SLEEP); + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); mpt_free_msg_frame(ioc, mf); /* attempt one retry for a timed out command */ if (!retry_count) { @@ -6904,6 +6904,172 @@ mpt_halt_firmware(MPT_ADAPTER *ioc) } EXPORT_SYMBOL(mpt_halt_firmware); +/** + * mpt_SoftResetHandler - Issues a less expensive reset + * @ioc: Pointer to MPT_ADAPTER structure + * @sleepFlag: Indicates if sleep or schedule must be called. + + * + * Returns 0 for SUCCESS or -1 if FAILED. + * + * Message Unit Reset - instructs the IOC to reset the Reply Post and + * Free FIFO's. All the Message Frames on Reply Free FIFO are discarded. + * All posted buffers are freed, and event notification is turned off. + * IOC doesnt reply to any outstanding request. This will transfer IOC + * to READY state. + **/ +int +mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag) +{ + int rc; + int ii; + u8 cb_idx; + unsigned long flags; + u32 ioc_state; + unsigned long time_count; + + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n", + ioc->name)); + + ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK; + + if (mpt_fwfault_debug) + mpt_halt_firmware(ioc); + + if (ioc_state == MPI_IOC_STATE_FAULT || + ioc_state == MPI_IOC_STATE_RESET) { + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "skipping, either in FAULT or RESET state!\n", ioc->name)); + return -1; + } + + if (ioc->bus_type == FC) { + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "skipping, because the bus type is FC!\n", ioc->name)); + return -1; + } + + spin_lock_irqsave(&ioc->taskmgmt_lock, flags); + if (ioc->ioc_reset_in_progress) { + spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + return -1; + } + ioc->ioc_reset_in_progress = 1; + spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + + rc = -1; + + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + if (MptResetHandlers[cb_idx]) + mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); + } + + spin_lock_irqsave(&ioc->taskmgmt_lock, flags); + if (ioc->taskmgmt_in_progress) { + spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + return -1; + } + spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + /* Disable reply interrupts (also blocks FreeQ) */ + CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); + ioc->active = 0; + time_count = jiffies; + + rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); + + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + if (MptResetHandlers[cb_idx]) + mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET); + } + + if (rc) + goto out; + + ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK; + if (ioc_state != MPI_IOC_STATE_READY) + goto out; + + for (ii = 0; ii < 5; ii++) { + /* Get IOC facts! Allow 5 retries */ + rc = GetIocFacts(ioc, sleepFlag, + MPT_HOSTEVENT_IOC_RECOVER); + if (rc == 0) + break; + if (sleepFlag == CAN_SLEEP) + msleep(100); + else + mdelay(100); + } + if (ii == 5) + goto out; + + rc = PrimeIocFifos(ioc); + if (rc != 0) + goto out; + + rc = SendIocInit(ioc, sleepFlag); + if (rc != 0) + goto out; + + rc = SendEventNotification(ioc, 1, sleepFlag); + if (rc != 0) + goto out; + + if (ioc->hard_resets < -1) + ioc->hard_resets++; + + /* + * At this point, we know soft reset succeeded. + */ + + ioc->active = 1; + CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); + + out: + spin_lock_irqsave(&ioc->taskmgmt_lock, flags); + ioc->ioc_reset_in_progress = 0; + ioc->taskmgmt_quiesce_io = 0; + ioc->taskmgmt_in_progress = 0; + spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + + if (ioc->active) { /* otherwise, hard reset coming */ + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + if (MptResetHandlers[cb_idx]) + mpt_signal_reset(cb_idx, ioc, + MPT_IOC_POST_RESET); + } + } + + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "SoftResetHandler: completed (%d seconds): %s\n", + ioc->name, jiffies_to_msecs(jiffies - time_count)/1000, + ((rc == 0) ? "SUCCESS" : "FAILED"))); + + return rc; +} + +/** + * mpt_Soft_Hard_ResetHandler - Try less expensive reset + * @ioc: Pointer to MPT_ADAPTER structure + * @sleepFlag: Indicates if sleep or schedule must be called. + + * + * Returns 0 for SUCCESS or -1 if FAILED. + * Try for softreset first, only if it fails go for expensive + * HardReset. + **/ +int +mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) { + int ret = -1; + + ret = mpt_SoftResetHandler(ioc, sleepFlag); + if (ret == 0) + return ret; + ret = mpt_HardResetHandler(ioc, sleepFlag); + return ret; +} +EXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler); + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Reset Handling diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 9718c8f2e95..e25dbfbb8fd 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -940,6 +940,7 @@ extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); +extern int mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag); extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); extern int mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 80421d2cf04..e6d71e20fa0 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -311,7 +311,7 @@ mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) 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_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); mpt_free_msg_frame(ioc, mf); } diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 76687126b57..e5e9bf3487d 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -2041,7 +2041,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) if (!timeleft) { /* On timeout reset the board */ mpt_free_msg_frame(ioc, mf); - mpt_HardResetHandler(ioc, CAN_SLEEP); + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); error = -ETIMEDOUT; goto out_unlock; } @@ -2226,7 +2226,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, if (!timeleft) { printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__); /* On timeout reset the board */ - mpt_HardResetHandler(ioc, CAN_SLEEP); + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); ret = -ETIMEDOUT; goto unmap; } @@ -2833,7 +2833,7 @@ mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc, if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET) goto out_free; if (!timeleft) - mpt_HardResetHandler(ioc, CAN_SLEEP); + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); goto out_free; } @@ -4717,7 +4717,7 @@ mptsas_broadcast_primative_work(struct fw_event_work *fw_event) if (issue_reset) { printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", ioc->name, __func__); - mpt_HardResetHandler(ioc, CAN_SLEEP); + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); } mptsas_free_fw_event(ioc, fw_event); } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 6796597dcee..929d584855d 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1711,7 +1711,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, if (issue_hard_reset) { printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", ioc->name, __func__); - retval = mpt_HardResetHandler(ioc, CAN_SLEEP); + retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); mpt_free_msg_frame(ioc, mf); } @@ -1991,7 +1991,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) /* If our attempts to reset the host failed, then return a failed * status. The host will be taken off line by the SCSI mid-layer. */ - retval = mpt_HardResetHandler(ioc, CAN_SLEEP); + retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); if (retval < 0) status = FAILED; else @@ -3040,7 +3040,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) if (!timeleft) { printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", ioc->name, __func__); - mpt_HardResetHandler(ioc, CAN_SLEEP); + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); mpt_free_msg_frame(ioc, mf); } goto out; -- cgit v1.2.3-70-g09d2 From 7d757f18554070e917f61e7caedf395f940cf853 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:13:10 +0530 Subject: [SCSI] mptfusion: Updated SCSI IO IOCTL error handling. Behavior changes only for IOCTLs that time out. Current behavior of Bus Reset remains the same for RAID Passthru Timeouts Current behavior of Diagnostic reset for any other type of IOCTL remains the same CHANGE: For IOCTL SCSI IOs that timeout, a Target Reset TM is sent, instead of Bus Reset. All error handing from that point is the same as what the driver currently does, which is to say that if the Device Reset TM fails it escalates do diagnostic reset. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 161 +++++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 75 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index e6d71e20fa0..e7fab5de16e 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -128,7 +128,6 @@ 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); static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc); -static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function); /* * Reset Handler cleanup function @@ -275,45 +274,6 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) return 1; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_timeout_expired - * - * Expecting an interrupt, however timed out. - * - */ -static void -mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) -{ - unsigned long flags; - - 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; - } - 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_Soft_Hard_ResetHandler(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) @@ -343,12 +303,8 @@ mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) return 0; } -/* mptctl_bus_reset - * - * Bus reset code. - * - */ -static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) +static int +mptctl_do_taskmgmt(MPT_ADAPTER *ioc, u8 tm_type, u8 bus_id, u8 target_id) { MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; @@ -359,13 +315,6 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) 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; - } mutex_lock(&ioc->taskmgmt_cmds.mutex); if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { @@ -375,15 +324,14 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) retval = 0; - /* Send request - */ 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)); + 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; + goto tm_done; } dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", @@ -392,10 +340,13 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) pScsiTm = (SCSITaskMgmt_t *) mf; memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t)); pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; - pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; - pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; - pScsiTm->TargetID = 0; - pScsiTm->Bus = 0; + pScsiTm->TaskType = tm_type; + if ((tm_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && + (ioc->bus_type == FC)) + pScsiTm->MsgFlags = + MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; + pScsiTm->TargetID = target_id; + pScsiTm->Bus = bus_id; pScsiTm->ChainOffset = 0; pScsiTm->Reserved = 0; pScsiTm->Reserved1 = 0; @@ -413,17 +364,16 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) timeout = 30; break; case SPI: - default: - timeout = 2; + default: + timeout = 10; break; } - dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "TaskMgmt type=%d timeout=%ld\n", - ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout)); + dtmprintk(ioc, + printk(MYIOC_s_DEBUG_FMT "TaskMgmt type=%d timeout=%ld\n", + ioc->name, tm_type, timeout)); 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)) @@ -432,17 +382,20 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc, sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP); if (retval != 0) { - dfailprintk(ioc, printk(MYIOC_s_ERR_FMT + dfailprintk(ioc, + printk(MYIOC_s_ERR_FMT "TaskMgmt send_handshake FAILED!" " (ioc %p, mf %p, rc=%d) \n", ioc->name, ioc, mf, retval)); + mpt_free_msg_frame(ioc, mf); mpt_clear_taskmgmt_in_progress_flag(ioc); - goto mptctl_bus_reset_done; + goto tm_done; } } /* Now wait for the command to complete */ 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)); @@ -452,14 +405,14 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) retval = 0; else retval = -1; /* return failure */ - goto mptctl_bus_reset_done; + goto tm_done; } 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; + goto tm_done; } pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply; @@ -467,7 +420,7 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) "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, + pScsiTmReply->TargetID, tm_type, le16_to_cpu(pScsiTmReply->IOCStatus), le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode, @@ -485,13 +438,71 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) retval = -1; /* return failure */ } - - mptctl_bus_reset_done: + tm_done: mutex_unlock(&ioc->taskmgmt_cmds.mutex); CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) return retval; } +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* mptctl_timeout_expired + * + * Expecting an interrupt, however timed out. + * + */ +static void +mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) +{ + unsigned long flags; + int ret_val = -1; + SCSIIORequest_t *scsi_req = (SCSIIORequest_t *) mf; + u8 function = mf->u.hdr.Function; + + 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; + } + spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + + + CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) + + if (ioc->bus_type == SAS) { + if (function == MPI_FUNCTION_SCSI_IO_REQUEST) + ret_val = mptctl_do_taskmgmt(ioc, + MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, + scsi_req->Bus, scsi_req->TargetID); + else if (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) + ret_val = mptctl_do_taskmgmt(ioc, + MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, + scsi_req->Bus, 0); + if (!ret_val) + return; + } else { + if ((function == MPI_FUNCTION_SCSI_IO_REQUEST) || + (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) + ret_val = mptctl_do_taskmgmt(ioc, + MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, + scsi_req->Bus, 0); + if (!ret_val) + return; + } + + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling Reset! \n", + ioc->name)); + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); + mpt_free_msg_frame(ioc, mf); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* mptctl_ioc_reset -- cgit v1.2.3-70-g09d2 From b3b97316d5861b1708cd7ef2df9989d12d97acb9 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:14:51 +0530 Subject: [SCSI] mptfusion: mpt config will do Hard Reset based upon retry counts mpt_config would only attempt a MUR before retrying the command. The driver will now retry a second time with a hard reset before leaving the function. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a4f023bd5d2..a6a57011ba6 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -6456,10 +6456,15 @@ out: issue_hard_reset = 0; printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", ioc->name, __func__); - mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); + if (retry_count == 0) { + if (mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP) != 0) + retry_count++; + } else + mpt_HardResetHandler(ioc, CAN_SLEEP); + mpt_free_msg_frame(ioc, mf); /* attempt one retry for a timed out command */ - if (!retry_count) { + if (retry_count < 2) { printk(MYIOC_s_INFO_FMT "Attempting Retry Config request" " type 0x%x, page 0x%x," -- cgit v1.2.3-70-g09d2 From 48959f1eae3068fefb3de05cdc0c2bd8f0f96c37 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:18:30 +0530 Subject: [SCSI] mptfusion: mpt_detach is called properly at the time of rmmod Current design of mptsas is as follow. MPTSAS will do probe() if pci id matches for available card in system, irrespective of mode of controller. If controller is I/T mode or I mode, things are fine. If controller is only in T mode, mptsas is not doing complete process of mptsas_probe(). It will only make sure IOC structure is created and IOC reference is available for mptstm driver. Now While removing module we should take care case of Target mode only mptsas. If we are removing IOC which is only in Target mode, We should only detach IOC instead of following rest of the cleanup process which is only required for T mode controller. Now For T mode controller, only part clean up is done instead of complete cleanup. mpt_detach will call early in case of Target mode only controller. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 6 ++++++ drivers/message/fusion/mptscsih.c | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index e5e9bf3487d..674461fb6a3 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -5073,6 +5073,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) struct mptsas_portinfo *p, *n; int i; + if (!ioc->sh) { + printk(MYIOC_s_INFO_FMT "IOC is in Target mode\n", ioc->name); + mpt_detach(pdev); + return; + } + mptsas_shutdown(pdev); mptsas_del_device_components(ioc); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 929d584855d..b966678e441 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1149,11 +1149,6 @@ mptscsih_remove(struct pci_dev *pdev) MPT_SCSI_HOST *hd; int sz1; - if(!host) { - mpt_detach(pdev); - return; - } - scsi_remove_host(host); if((hd = shost_priv(host)) == NULL) -- cgit v1.2.3-70-g09d2 From ffb7fef32b98fff773a5a6882ae4f8aee65a7708 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:20:38 +0530 Subject: [SCSI] mptfusion: Proper bus_type check is added Added proper bus_type check before processing event/ reset handler. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptfc.c | 5 ++++- drivers/message/fusion/mptsas.c | 3 +++ drivers/message/fusion/mptspi.c | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 33f7256055b..8b3ff2d43fb 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -1358,6 +1358,9 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) unsigned long flags; int rc=1; + if (ioc->bus_type != FC) + return 0; + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); @@ -1396,7 +1399,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) unsigned long flags; rc = mptscsih_ioc_reset(ioc,reset_phase); - if (rc == 0) + if ((ioc->bus_type != FC) || (!rc)) return rc; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 674461fb6a3..7f217445cd9 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -4779,6 +4779,9 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) struct fw_event_work *fw_event; unsigned long delay; + if (ioc->bus_type != SAS) + return 0; + /* events turned off due to host reset or driver unloading */ if (ioc->fw_events_off) return 0; diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index e44365193fd..8820591a693 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1152,6 +1152,9 @@ mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); + if (ioc->bus_type != SPI) + return 0; + if (hd && event == MPI_EVENT_INTEGRATED_RAID) { int reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; @@ -1283,6 +1286,8 @@ mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) int rc; rc = mptscsih_ioc_reset(ioc, reset_phase); + if ((ioc->bus_type != SPI) || (!rc)) + return rc; /* only try to do a renegotiation if we're properly set up * if we get an ioc fault on bringup, ioc->sh will be NULL */ -- cgit v1.2.3-70-g09d2 From f8c23bde85091b696e72d00bc6aa16216a9862f7 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:21:34 +0530 Subject: [SCSI] mptfusion: Setting period,offset and width for SPI driver Set factor, offset and width while target negotiation. Added config timeout 60 seconds. It was missing for only mptspi_read_spi_device_pg0 Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptspi.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 8820591a693..1abaa5d01ae 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -210,6 +210,10 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, target->maxOffset = offset; target->maxWidth = width; + spi_min_period(scsi_target(sdev)) = factor; + spi_max_offset(scsi_target(sdev)) = offset; + spi_max_width(scsi_target(sdev)) = width; + target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; /* Disable unused features. @@ -558,6 +562,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; cfg.dir = 0; cfg.pageAddr = starget->id; + cfg.timeout = 60; if (mpt_config(ioc, &cfg)) { starget_printk(KERN_ERR, starget, MYIOC_s_FMT "mpt_config failed\n", ioc->name); -- cgit v1.2.3-70-g09d2 From 08f5c5c23d52aa385ff304becffb0e0c37cedfe5 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:22:45 +0530 Subject: [SCSI] mptfusion: sanity check for vdevice pointer is added Added sanity checks before accessing vdevice and added vdevice->deleted setting for mptfc. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 7 +++++++ drivers/message/fusion/mptfc.c | 17 +++++++++++++++++ drivers/message/fusion/mptscsih.c | 2 ++ 3 files changed, 26 insertions(+) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index e7fab5de16e..f06b29193b4 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1329,6 +1329,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) if (ioc->sh) { shost_for_each_device(sdev, ioc->sh) { vdevice = sdev->hostdata; + if (vdevice == NULL || vdevice->vtarget == NULL) + continue; if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) continue; @@ -1450,6 +1452,8 @@ mptctl_gettargetinfo (unsigned long arg) if (!maxWordsLeft) continue; vdevice = sdev->hostdata; + if (vdevice == NULL || vdevice->vtarget == NULL) + continue; if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) continue; @@ -1978,6 +1982,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) struct scsi_target *starget = scsi_target(sdev); VirtTarget *vtarget = starget->hostdata; + if (vtarget == NULL) + continue; + if ((pScsiReq->TargetID == vtarget->id) && (pScsiReq->Bus == vtarget->channel) && (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 8b3ff2d43fb..b5f03ad8156 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -482,6 +482,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) if (vtarget) { vtarget->id = pg0->CurrentTargetID; vtarget->channel = pg0->CurrentBus; + vtarget->deleted = 0; } } *((struct mptfc_rport_info **)rport->dd_data) = ri; @@ -1092,6 +1093,8 @@ mptfc_setup_reset(struct work_struct *work) container_of(work, MPT_ADAPTER, fc_setup_reset_work); u64 pn; struct mptfc_rport_info *ri; + struct scsi_target *starget; + VirtTarget *vtarget; /* reset about to happen, delete (block) all rports */ list_for_each_entry(ri, &ioc->fc_rports, list) { @@ -1099,6 +1102,12 @@ mptfc_setup_reset(struct work_struct *work) ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED; fc_remote_port_delete(ri->rport); /* won't sleep */ ri->rport = NULL; + starget = ri->starget; + if (starget) { + vtarget = starget->hostdata; + if (vtarget) + vtarget->deleted = 1; + } pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; @@ -1119,6 +1128,8 @@ mptfc_rescan_devices(struct work_struct *work) int ii; u64 pn; struct mptfc_rport_info *ri; + struct scsi_target *starget; + VirtTarget *vtarget; /* start by tagging all ports as missing */ list_for_each_entry(ri, &ioc->fc_rports, list) { @@ -1146,6 +1157,12 @@ mptfc_rescan_devices(struct work_struct *work) MPT_RPORT_INFO_FLAGS_MISSING); fc_remote_port_delete(ri->rport); /* won't sleep */ ri->rport = NULL; + starget = ri->starget; + if (starget) { + vtarget = starget->hostdata; + if (vtarget) + vtarget->deleted = 1; + } pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index b966678e441..90a1dff7eb8 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2339,6 +2339,8 @@ mptscsih_slave_destroy(struct scsi_device *sdev) starget = scsi_target(sdev); vtarget = starget->hostdata; vdevice = sdev->hostdata; + if (!vdevice) + return; mptscsih_search_running_cmds(hd, vdevice); vtarget->num_luns--; -- cgit v1.2.3-70-g09d2 From 69b2e9b4431798645e3d8fb51413db97c9845db1 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:23:19 +0530 Subject: [SCSI] mptfusion: Task abort is not supported for Volumes 1) corrected return value as SUCCESS instead of 0. 2) Added check in mptscsih_abort. mptfusion do not support task abort for Volumes. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptscsih.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 90a1dff7eb8..7bd4c0fc23c 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1723,6 +1723,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) case FC: return 40; case SAS: + return 30; case SPI: default: return 10; @@ -1772,7 +1773,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) ioc->name, SCpnt)); SCpnt->result = DID_NO_CONNECT << 16; SCpnt->scsi_done(SCpnt); - retval = 0; + retval = SUCCESS; goto out; } @@ -1787,6 +1788,17 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) goto out; } + /* Task aborts are not supported for volumes. + */ + if (vdevice->vtarget->raidVolume) { + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "task abort: raid volume (sc=%p)\n", + ioc->name, SCpnt)); + SCpnt->result = DID_RESET << 16; + retval = FAILED; + goto out; + } + /* Find this command */ if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) { -- cgit v1.2.3-70-g09d2 From 568da76929392c9feb60a25383250dd6cfa68e05 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:23:50 +0530 Subject: [SCSI] mptfusion: Check for command status is added after completion. 1) Corrected name string as "MPT SAS HOST" 2) Added proper check conditions for MPT_MGMT_STATUS_COMMAND_GOOD. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 7f217445cd9..77f21e068da 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1894,7 +1894,7 @@ static struct scsi_host_template mptsas_driver_template = { .module = THIS_MODULE, .proc_name = "mptsas", .proc_info = mptscsih_proc_info, - .name = "MPT SPI Host", + .name = "MPT SAS Host", .info = mptscsih_info, .queuecommand = mptsas_qcmd, .target_alloc = mptsas_target_alloc, @@ -2038,11 +2038,13 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ); - if (!timeleft) { - /* On timeout reset the board */ + if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { + error = -ETIME; mpt_free_msg_frame(ioc, mf); - mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); - error = -ETIMEDOUT; + if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET) + goto out_unlock; + if (!timeleft) + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); goto out_unlock; } @@ -2223,11 +2225,14 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf); timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ); - if (!timeleft) { - printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__); - /* On timeout reset the board */ - mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); - ret = -ETIMEDOUT; + if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { + ret = -ETIME; + mpt_free_msg_frame(ioc, mf); + mf = NULL; + if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET) + goto unmap; + if (!timeleft) + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); goto unmap; } mf = NULL; @@ -4098,6 +4103,7 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) cfg.pageAddr = (channel << 8) + id; cfg.cfghdr.hdr = &hdr; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT; if (mpt_config(ioc, &cfg) != 0) goto out; -- cgit v1.2.3-70-g09d2 From f18a8927f6779f5dc9dc4327522c8a12f2cf31b9 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:24:20 +0530 Subject: [SCSI] mptfusion: Event data alignment with 4 byte. event_data needs to be 4 byte aligned to makes sure there is no unaligned memory access take place. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h index 953c2bfcf6a..7b249edbda7 100644 --- a/drivers/message/fusion/mptsas.h +++ b/drivers/message/fusion/mptsas.h @@ -110,7 +110,7 @@ struct fw_event_work { MPT_ADAPTER *ioc; u32 event; u8 retries; - u8 event_data[1]; + u8 __attribute__((aligned(4))) event_data[1]; }; struct mptsas_discovery_event { -- cgit v1.2.3-70-g09d2 From 0cf0f23c286459625eb5cbf9934135ff3156ce95 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:24:57 +0530 Subject: [SCSI] mptfusion: Proper error handling is added after mpt_config timeout Added proper error handling after mpt_config. Now check of MPI_IOCSTATUS_CONFIG_INVALID_PAGE is added. If error is MPI_IOCSTATUS_CONFIG_INVALID_PAGE, driver will return -ENODEV. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 77f21e068da..ac000e83db0 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -2523,6 +2523,12 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; error = mpt_config(ioc, &cfg); + + if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) { + error = -ENODEV; + goto out_free_consistent; + } + if (error) goto out_free_consistent; @@ -2599,14 +2605,14 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; error = mpt_config(ioc, &cfg); - if (error) - goto out_free_consistent; - - if (!buffer->NumPhys) { + if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) { error = -ENODEV; goto out_free_consistent; } + if (error) + goto out_free_consistent; + /* save config data */ port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1; port_info->phy_info = kcalloc(port_info->num_phys, @@ -2682,7 +2688,7 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) { error = -ENODEV; - goto out; + goto out_free_consistent; } if (error) -- cgit v1.2.3-70-g09d2 From 4f581b97314a2da96fa4d611ebfb586b2828b027 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 18 Mar 2010 19:26:02 +0530 Subject: [SCSI] mptfusion: Bump version 03.04.15 Upgrade version from 3.04.14 to 3.04.15 Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index e25dbfbb8fd..b613eb3d470 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -76,8 +76,8 @@ #define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.04.14" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.14" +#define MPT_LINUX_VERSION_COMMON "3.04.15" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.15" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ -- cgit v1.2.3-70-g09d2