--- ./source/private_module/sio/stub_v3/stub_sio_timeout.c	2018-04-20 08:27:24.000000000 +0000
+++ ./source/private_module/sio/stub_v3/stub_sio_timeout.c.hotpatch	2021-03-02 04:53:16.000000000 +0000
@@ -7,7 +7,6 @@
 * IOʱ̴
 *     ע
 **************************************************************************/
-
 #include "../sio_def.h"
 #include "bdm_inner_intf.h"
 #include "obs_public.h"
@@ -17,6 +16,7 @@
 #include "sio_nvme_intf.h"
 #include "bdm_nvme_intf.h"
 /* Dorado 5000 modified end */
+#include "mp_path.h"
 
 MODULE_ID(PID_BDM_SIO);
 
@@ -524,8 +524,8 @@
 
     return;
 }
+void sioDoDiskRecovery(SIO_QUEUE_S *queue);
 /**************************************************************************
-   : sioChooseDeviceRecoveryHandle
      :豸ͼ·ѡabortʧ֮Ĵʽ
  : SIO_QUEUE_S *queue
  : 
@@ -547,8 +547,7 @@
             
             sioDoPrivateDeviceRecovery(queue);
         }
-        else
-        {
+        else {
             sioClearPrivateDeviceRecoveryFlag(queue);
             spin_unlock(&queue->dispQLock);
             
@@ -558,14 +557,15 @@
             sioDoCommonDeviceRecovery(queue);
         }
     }
-    else
-    {
+    else if (SCSI_DEVICE_TYPE_DISK == queue->disk->type) {
+        sioDoDiskRecovery(queue);
+    } else {
         sioDoCommonDeviceRecovery(queue);
     }
 
     return;
 }
-/*End Modified by c00230409 ALMCA2017121819364398 20171231*/
+
 /*Begin Modified by j00285232 SR_F455BAFE-388F-4cf9-BA56-0F2A7551ADEE 20170602*/
 /**************************************************************************
   : sioDeviceRecovery
@@ -1246,3 +1246,317 @@
 EXPORT_SYMBOL(sioDiskIOFastReturnWithTimeoutError);
 /*End Modified by j00285232 SR.SF-0000248697.001 20180304*/
 
+int32_t mpGetLunPathFrameWwn(MP_PATH_DRV_DATA_S *path, uint64_t *wwn)
+{
+    LUN_PATH_S *lunPath = NULL;
+
+    if (NULL == path || NULL == wwn)
+    {
+        BDM_PRINT_LIMIT(BDM_LOG_INTERVAL_FIVE_MIN, 2, DBG_LOG_ERROR, DBG_LOGID_NEW, 
+            "SPH030:Param is invalid, path(%p), wwn(%p).", path, wwn);
+        return RETURN_ERROR;
+    }
+
+    lunPath = container_of(path, LUN_PATH_S, pathData);
+    *wwn = lunPath->diskFatherWwn;
+
+    return RETURN_OK;
+}
+
+int32_t hdmGetDiskLoopStatusSync(uint64_t frameWwn, uint32_t slotId, uint32_t *status)
+{
+    int32_t ret = RETURN_ERROR;    
+    /*ڻ״̬*/
+    DMI_DISK_STATUS_E diskStatus = DMI_DISK_STATUS_BUTT;
+    
+    /*Begin modify by h00405124 DTS2019022209565 20190313*/
+    /*DMIӿڲѯӲڻ״̬*/
+    ret= OperateDisk(GET_DISK_STATUS_INLOOP, frameWwn, slotId, (void*)&diskStatus,    
+                        sizeof(DMI_DISK_STATUS_E));
+    BDM_PRINT_LIMIT_PERIOD(60*HZ, 1, DBG_LOG_INFO,DBG_LOGID_NEW,
+                "SPH030:Get disk loop status ret:%d wwn: 0x%llx slotId: %u status: %u.",
+                ret, frameWwn, slotId, diskStatus);
+    if (RETURN_OK != ret)
+    {
+        BDM_PRINT_LIMIT_PERIOD(300*HZ, 3, DBG_LOG_ERROR, DBG_LOGID_NEW,
+                     "SPH030:DidNexus:get disk loop status failed: ret %d,loop status %u." \
+                     "wwn 0x%llx, slot %u.",
+                     ret, diskStatus, frameWwn, slotId);
+        return RETURN_ERROR; 
+    }
+    /*End modify by h00405124 DTS2019022209565 20190313*/
+    
+    *status = (uint32_t)diskStatus;
+    return RETURN_OK;      
+}
+
+int32_t hdmAdapterPhySwitchPatch(BDM_DISK_PHY_ACTION_E bdmSwitch, DMI_SWITCH_STATE_E *dmiSwitch)
+{
+    switch (bdmSwitch)
+    {
+        case BDM_DISK_PHY_ACTION_CLOSE:
+            *dmiSwitch = DMI_SWITCH_CLOSE;
+            break;
+        /*Begin modified by w90004841 20150928 DTS2015092302238*/
+        case BDM_DISK_PHY_ACTION_LOG_AND_CLOSE:
+            *dmiSwitch = DMI_SWITCH_CLOSE;
+            break;
+        /*End modified by w90004841 20150928 DTS2015092302238*/
+        case BDM_DISK_PHY_ACTION_OPEN:
+            *dmiSwitch = DMI_SWITCH_OPEN;
+            break;
+        case BDM_DISK_PHY_ACTION_BUTT:
+        default:
+            return RETURN_ERROR;
+    }
+    
+    return RETURN_OK;
+}
+
+int32_t hdmDiskPhySwitchSync(uint64_t frameWwn, uint32_t slotId, uint8_t switchFlag, bool *state)
+{
+    int32_t ret = RETURN_ERROR;
+    DMI_SWITCH_STATE_E dmiSwitch = DMI_SWITCH_STATE_BUTT;
+    
+    ret = hdmAdapterPhySwitchPatch((BDM_DISK_PHY_ACTION_E)switchFlag, &dmiSwitch);
+    if (RETURN_OK != ret)
+    {
+        DBG_LogError(DBG_LOGID_NEW, 
+                     "SPH030:Adapter bdm phy switch(switch value %u) to dmi switch fail.",
+                     switchFlag);
+        return RETURN_ERROR;
+    }
+    
+    #if defined(WIN32)  && !defined(_NEW_DT)
+    DBG_LogInfo(DBG_LOGID_NEW,
+                "SPH030:Disk physwitch always succeed in simulator, wwn: 0x%llx, slot id: %u, switchFlag: %u.",
+                frameWwn, slotId, switchFlag); 
+    ret = RETURN_OK;
+    *state = TRUE;
+    #else
+    /*Begin modify by h00405124 DTS2019022209565 20190313*/
+    ret= OperateDisk(SET_DISK_SWITCH, frameWwn, slotId, (void*)(&dmiSwitch), sizeof(DMI_SWITCH_STATE_E));
+    SMART_TP_CALL(HDM_SWITCH_PHY_FAIL, &ret);
+    if(RETURN_OK != ret)
+    {
+        DBG_LogError(DBG_LOGID_NEW,
+                     "SPH030:Disk switch phy fail, wwn: 0x%llx, slot id: %u, switchFlag: %u.",
+                     frameWwn, slotId, dmiSwitch);
+        *state = FALSE;
+        return RETURN_ERROR;
+    }
+
+    DBG_LogInfo(DBG_LOGID_NEW,
+                 "SPH030:Disk switch phy succeed, wwn: 0x%llx, slot id: %u, switchFlag:%u.",
+                 frameWwn, slotId, switchFlag);
+    /*End modify by h00405124 DTS2019022209565 20190313*/
+    ret = RETURN_OK;
+    *state = TRUE;
+    #endif
+
+    return ret;   
+}
+
+int32_t sioSwitchDiskPhySync(uint64_t frameWwn, uint32_t slotId, uint32_t action)
+{
+    bool state = FALSE;
+    int32_t ret = RETURN_ERROR;
+    /*Begin modify by h00405124 DTS2019022209565 20190313*/
+    if (unlikely(action >= (uint32_t)BDM_DISK_PHY_ACTION_BUTT))
+    {
+        BDM_PRINT_LIMIT_PERIOD(SIO_LOG_INTERVAL_ONE_MINUTE, 1, DBG_LOG_ERROR,LOG_ID_SIO_02DD, 
+            "BDM_EH:SPH030:wwn:0x%llx slotId:%u set phy failed.Invalid action(%u).", 
+            frameWwn, slotId, action);
+        return RETURN_ERROR;
+    }
+         
+    ret = hdmDiskPhySwitchSync(frameWwn, slotId, (uint8_t)action, &state);
+    if (unlikely(RETURN_OK != ret))
+    {
+        BDM_PRINT_LIMIT_PERIOD(SIO_LOG_INTERVAL_ONE_MINUTE, 1, DBG_LOG_ERROR, LOG_ID_SIO_02DD, 
+            "BDM_EH:SPH030:wwn:0x%llx slotId:%u switch phy failed,action:%u.", frameWwn, slotId, action);
+        return RETURN_ERROR;
+    }
+    /*End modify by h00405124 DTS2019022209565 20190313*/
+    return (TRUE == state) ? RETURN_OK : RETURN_ERROR;    
+}
+
+#define SIO_CHECK_DISK_IN_LOOP_STATUS_CNT (2)
+#define SIO_CHECK_DISK_IN_LOOP_STATUS_DELAY (3000)
+#define IS_DISK_IN_LOOP_STATE(LoopState) ((DMI_DISK_STATUS_NOT_INLOOP < (LoopState)) && (DMI_DISK_STATUS_BUTT > (LoopState)))
+int32_t sioCheckDiskNotInLoop(uint64_t frameWwn, uint32_t slotId)
+{
+    int32_t  ret = RETURN_ERROR;
+    uint32_t idx = 0;
+    uint32_t status = DMI_DISK_STATUS_BUTT;
+    
+    for (idx = 0; idx < SIO_CHECK_DISK_IN_LOOP_STATUS_CNT; idx++)
+    {
+        LVOS_msleep(SIO_CHECK_DISK_IN_LOOP_STATUS_DELAY);
+        ret = hdmGetDiskLoopStatusSync(frameWwn, slotId, &status);
+        if (RETURN_OK != ret)
+        {
+            continue;
+        }
+
+        if (IS_DISK_IN_LOOP_STATE(status) || (DMI_DISK_STATUS_BUTT == status))
+        {
+            continue;
+        }
+        
+        if (status <= DMI_DISK_STATUS_NOT_INLOOP)
+        {
+            BDM_PRINT_LIMIT_PERIOD(SIO_LOG_INTERVAL_ONE_MINUTE, 1, DBG_LOG_INFO, LOG_ID_SIO_02DD, 
+                                    "BDM_EH:SPH030:wwn:0x%llx slotId:%u get loop status:%u success.", 
+                                    frameWwn, slotId, status);
+            return RETURN_OK;
+        } 
+    }
+
+    return RETURN_ERROR;
+}
+
+#define SIO_RESET_DELAY_TIME 10000     /* ʱ10 */
+void sioDeviceResetFailHandle(SCSI_DISK_DEVICE_S *disk, 
+                                                        MP_PATH_DRV_DATA_S *path, 
+                                                        SD_CMND_S *resetCmd, 
+                                                        struct list_head *ehList)
+{
+    SIO_S *sio = NULL;
+    int32_t ret = RETURN_OK;
+    struct list_head *pos = NULL;
+    struct list_head *nex = NULL;
+    uint64_t diskFrameWwn = INVALID_VALUE64;
+    
+    /*Begin modify by h00405124 DTS2019022209565 20190313*/
+    if (RETURN_OK == mpGetLunPathFrameWwn(path, &diskFrameWwn))
+    {
+        ret = sioSwitchDiskPhySync(diskFrameWwn, disk->slotId, BDM_DISK_PHY_ACTION_CLOSE);
+    }
+    else 
+    {
+        ret = RETURN_ERROR;
+    }
+
+    if (unlikely(RETURN_OK != ret))
+    {
+        BDM_ADJUSTABLE_LOG(DBG_LOGID_BUTT, "BDM_EH:SPH030:Close phy ret:%d frameId:%u slotId:%u sdId:%u.",
+                 ret, disk->frameId, disk->slotId,disk->device.sdevId);
+        /*IOʱ10뷵أ*/
+        list_for_each_safe(pos, nex, ehList) 
+        {
+            sio = list_entry(pos, SIO_S, node);
+            if (sioCheckIsLunAddrMatch(resetCmd, sio->req))
+            {  
+                list_del(pos);
+                /*Begin  Modified by l00472145 DTS2018091110127 2018-09-23*/
+                sio->req->ops = &s_sioDeviceRetDelayReqOps;
+                IOD_ADD_DELAY_STARTQ(SIO_RESET_DELAY_TIME, sio->req);
+                /*End  Modified by l00472145 DTS2018091110127 2018-09-23*/
+            }            
+        }
+        return;
+    }
+
+    /*ڻź*/      
+    ret = sioCheckDiskNotInLoop(diskFrameWwn, disk->slotId);
+    BDM_ADJUSTABLE_LOG(DBG_LOGID_BUTT, "BDM_EH:SPH030:Check loop status ret:%u "
+                               "frameId:%u slotId:%u sdId:%u.",
+                                ret, disk->frameId, disk->slotId,disk->device.sdevId);
+    if (RETURN_OK == ret)
+    {
+        (void)sioSwitchDiskPhySync(diskFrameWwn, disk->slotId, BDM_DISK_PHY_ACTION_OPEN);
+        /*λIOԷ*/
+        BDM_PRINT_LIMIT_PERIOD(SIO_LOG_INTERVAL_ONE_MINUTE, 1, DBG_LOG_INFO,LOG_ID_SIO_0031,
+                                                    "BDM_EH:SPH030:open disk phy success,frameId:%u slotId:%u sdId:%u sn:%s.",
+                                                    disk->frameId, disk->slotId, disk->device.sdevId, disk->sn);
+        return;
+    }
+    /*End modify by h00405124 DTS2019022209565 20190313*/
+    /*IOʱ10뷵أ*/
+    list_for_each_safe(pos, nex, ehList) 
+    {
+        sio = list_entry(pos, SIO_S, node);
+        if (sioCheckIsLunAddrMatch(resetCmd, sio->req))
+        {  
+            list_del(pos);
+            /*Begin  Modified by l00472145 DTS2018091110127 2018-09-23*/
+            sio->req->ops = &s_sioDeviceRetDelayReqOps;
+            IOD_ADD_DELAY_STARTQ(SIO_RESET_DELAY_TIME, sio->req);
+            /*End  Modified by l00472145 DTS2018091110127 2018-09-23*/
+        }
+    }
+    return;
+}
+
+void sioDoDiskRecovery(SIO_QUEUE_S *queue)
+{
+    SIO_S *sio = NULL;
+    MP_PATH_DRV_DATA_S *path = NULL;
+    bool isRecoverSuccess = B_TRUE;
+    int32_t ret = RETURN_OK;
+    struct list_head *pos = NULL;
+    struct list_head *nex = NULL;
+    struct list_head ehList;
+    SD_CMND_S resetCmd;
+    SCSI_DISK_DEVICE_S *sddisk = NULL;
+
+    INIT_LIST_HEAD(&ehList);
+
+    /* BDM R1 T11A-919 add by w90006892 2012/10/18 begin */
+    sdGetScsiDevice(queue->disk);
+    sddisk = SD_GENERIC_TO_DISK(queue->disk);
+    /* BDM R1 T11A-919 add by w90006892 2012/10/18 end */
+   
+    sioPrintQueue(queue);
+    
+    spin_lock(&queue->dispQLock); /*performance opt begin*/
+    list_splice_init(&queue->ehSioList, &ehList);    
+    spin_unlock(&queue->dispQLock); /*performance opt begin*/
+    
+    while(!list_empty(&ehList))
+    {
+        pos = ehList.next;
+        sio = list_entry(pos, SIO_S, node);
+        path = mpGetCurrentIOPathIntf(sio->req);
+/* Dorado 5000 modified begin */
+        resetCmd = *(SD_CMND_S *)(SIO_REQ_TO_CMD(sio->req));
+/* Dorado 5000 modified end */
+
+        /* reqӦ·device rest */
+        ret = sioDeviceReset(sio, path);
+        isRecoverSuccess = (RETURN_OK == ret) ? B_TRUE : B_FALSE;
+        /*Begin Modified by l00245290 DTS2015011313306 20150112*/
+        /*Begin Modified by t00352166  DTS2016042306860   20160423*/
+        if (RETURN_OK != ret)
+        {
+            sioDeviceResetFailHandle(sddisk, sio->mpPriv.path, &resetCmd, &ehList);
+        }
+        /*End Modified by l00245290 DTS2017030308202 20150112*/
+        /*End Modified by t00352166  DTS2016042306860   20160423*/
+        /*End Modified by l00245290 DTS2015011313306 20150112*/
+        /* device rest·ϵreq */
+        list_for_each_safe(pos, nex, &ehList) 
+        {
+            sio = list_entry(pos, SIO_S, node);
+            if (sioCheckIsLunAddrMatch(&resetCmd, sio->req))
+            {
+                list_del(pos);
+                sioDeviceFlushReq(sio, isRecoverSuccess);
+            }
+        }
+    }
+
+    BDM_ADJUSTABLE_LOG(LOG_ID_SIO_0041,
+                 "BDM_EH:SPH030:recovery device (SdevId %d) queue 0x%p finish.", 
+                 queue->disk->sdevId,
+                 queue);
+    
+    sioDeviceUnhangIo(queue);
+    /* BDM R1 T11A-919 add by w90006892 2012/10/18 begin */
+    sdPutScsiDevice(queue->disk);
+    /* BDM R1 T11A-919 add by w90006892 2012/10/18 end */
+
+    return;
+}
+
