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