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 |
