diff options
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 177 |
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 | } |
6905 | EXPORT_SYMBOL(mpt_halt_firmware); | 6910 | EXPORT_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 | **/ | ||
6926 | int | ||
6927 | mpt_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 | **/ | ||
7066 | int | ||
7067 | mpt_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 | } | ||
7076 | EXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler); | ||
7077 | |||
6907 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 7078 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
6908 | /* | 7079 | /* |
6909 | * Reset Handling | 7080 | * Reset Handling |