aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptbase.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r--drivers/message/fusion/mptbase.c177
1 files changed, 174 insertions, 3 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 5382b5a44aff..a6a57011ba6c 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)
5064 if (!timeleft) { 5064 if (!timeleft) {
5065 printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n", 5065 printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n",
5066 ioc->name, __func__); 5066 ioc->name, __func__);
5067 mpt_HardResetHandler(ioc, CAN_SLEEP); 5067 mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
5068 mpt_free_msg_frame(ioc, mf); 5068 mpt_free_msg_frame(ioc, mf);
5069 } 5069 }
5070 goto out; 5070 goto out;
@@ -6456,10 +6456,15 @@ out:
6456 issue_hard_reset = 0; 6456 issue_hard_reset = 0;
6457 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", 6457 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
6458 ioc->name, __func__); 6458 ioc->name, __func__);
6459 mpt_HardResetHandler(ioc, CAN_SLEEP); 6459 if (retry_count == 0) {
6460 if (mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP) != 0)
6461 retry_count++;
6462 } else
6463 mpt_HardResetHandler(ioc, CAN_SLEEP);
6464
6460 mpt_free_msg_frame(ioc, mf); 6465 mpt_free_msg_frame(ioc, mf);
6461 /* attempt one retry for a timed out command */ 6466 /* attempt one retry for a timed out command */
6462 if (!retry_count) { 6467 if (retry_count < 2) {
6463 printk(MYIOC_s_INFO_FMT 6468 printk(MYIOC_s_INFO_FMT
6464 "Attempting Retry Config request" 6469 "Attempting Retry Config request"
6465 " type 0x%x, page 0x%x," 6470 " type 0x%x, page 0x%x,"
@@ -6904,6 +6909,172 @@ mpt_halt_firmware(MPT_ADAPTER *ioc)
6904} 6909}
6905EXPORT_SYMBOL(mpt_halt_firmware); 6910EXPORT_SYMBOL(mpt_halt_firmware);
6906 6911
6912/**
6913 * mpt_SoftResetHandler - Issues a less expensive reset
6914 * @ioc: Pointer to MPT_ADAPTER structure
6915 * @sleepFlag: Indicates if sleep or schedule must be called.
6916
6917 *
6918 * Returns 0 for SUCCESS or -1 if FAILED.
6919 *
6920 * Message Unit Reset - instructs the IOC to reset the Reply Post and
6921 * Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.
6922 * All posted buffers are freed, and event notification is turned off.
6923 * IOC doesnt reply to any outstanding request. This will transfer IOC
6924 * to READY state.
6925 **/
6926int
6927mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6928{
6929 int rc;
6930 int ii;
6931 u8 cb_idx;
6932 unsigned long flags;
6933 u32 ioc_state;
6934 unsigned long time_count;
6935
6936 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n",
6937 ioc->name));
6938
6939 ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
6940
6941 if (mpt_fwfault_debug)
6942 mpt_halt_firmware(ioc);
6943
6944 if (ioc_state == MPI_IOC_STATE_FAULT ||
6945 ioc_state == MPI_IOC_STATE_RESET) {
6946 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6947 "skipping, either in FAULT or RESET state!\n", ioc->name));
6948 return -1;
6949 }
6950
6951 if (ioc->bus_type == FC) {
6952 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6953 "skipping, because the bus type is FC!\n", ioc->name));
6954 return -1;
6955 }
6956
6957 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6958 if (ioc->ioc_reset_in_progress) {
6959 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6960 return -1;
6961 }
6962 ioc->ioc_reset_in_progress = 1;
6963 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6964
6965 rc = -1;
6966
6967 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6968 if (MptResetHandlers[cb_idx])
6969 mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
6970 }
6971
6972 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6973 if (ioc->taskmgmt_in_progress) {
6974 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6975 return -1;
6976 }
6977 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6978 /* Disable reply interrupts (also blocks FreeQ) */
6979 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
6980 ioc->active = 0;
6981 time_count = jiffies;
6982
6983 rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
6984
6985 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6986 if (MptResetHandlers[cb_idx])
6987 mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
6988 }
6989
6990 if (rc)
6991 goto out;
6992
6993 ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
6994 if (ioc_state != MPI_IOC_STATE_READY)
6995 goto out;
6996
6997 for (ii = 0; ii < 5; ii++) {
6998 /* Get IOC facts! Allow 5 retries */
6999 rc = GetIocFacts(ioc, sleepFlag,
7000 MPT_HOSTEVENT_IOC_RECOVER);
7001 if (rc == 0)
7002 break;
7003 if (sleepFlag == CAN_SLEEP)
7004 msleep(100);
7005 else
7006 mdelay(100);
7007 }
7008 if (ii == 5)
7009 goto out;
7010
7011 rc = PrimeIocFifos(ioc);
7012 if (rc != 0)
7013 goto out;
7014
7015 rc = SendIocInit(ioc, sleepFlag);
7016 if (rc != 0)
7017 goto out;
7018
7019 rc = SendEventNotification(ioc, 1, sleepFlag);
7020 if (rc != 0)
7021 goto out;
7022
7023 if (ioc->hard_resets < -1)
7024 ioc->hard_resets++;
7025
7026 /*
7027 * At this point, we know soft reset succeeded.
7028 */
7029
7030 ioc->active = 1;
7031 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
7032
7033 out:
7034 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7035 ioc->ioc_reset_in_progress = 0;
7036 ioc->taskmgmt_quiesce_io = 0;
7037 ioc->taskmgmt_in_progress = 0;
7038 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7039
7040 if (ioc->active) { /* otherwise, hard reset coming */
7041 for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7042 if (MptResetHandlers[cb_idx])
7043 mpt_signal_reset(cb_idx, ioc,
7044 MPT_IOC_POST_RESET);
7045 }
7046 }
7047
7048 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7049 "SoftResetHandler: completed (%d seconds): %s\n",
7050 ioc->name, jiffies_to_msecs(jiffies - time_count)/1000,
7051 ((rc == 0) ? "SUCCESS" : "FAILED")));
7052
7053 return rc;
7054}
7055
7056/**
7057 * mpt_Soft_Hard_ResetHandler - Try less expensive reset
7058 * @ioc: Pointer to MPT_ADAPTER structure
7059 * @sleepFlag: Indicates if sleep or schedule must be called.
7060
7061 *
7062 * Returns 0 for SUCCESS or -1 if FAILED.
7063 * Try for softreset first, only if it fails go for expensive
7064 * HardReset.
7065 **/
7066int
7067mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) {
7068 int ret = -1;
7069
7070 ret = mpt_SoftResetHandler(ioc, sleepFlag);
7071 if (ret == 0)
7072 return ret;
7073 ret = mpt_HardResetHandler(ioc, sleepFlag);
7074 return ret;
7075}
7076EXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler);
7077
6907/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 7078/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6908/* 7079/*
6909 * Reset Handling 7080 * Reset Handling