[SRP] failed session recovery
authorleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 7 Apr 2008 11:03:19 +0000 (11:03 +0000)
committerleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 7 Apr 2008 11:03:19 +0000 (11:03 +0000)
Proposed by: Alex Estrin [alex.estrin@qlogic.com]

git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1046 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

ulp/srp/kernel/srp_connection.c
ulp/srp/kernel/srp_connection.h
ulp/srp/kernel/srp_data_path.c
ulp/srp/kernel/srp_driver.c
ulp/srp/kernel/srp_hba.c
ulp/srp/kernel/srp_hba.h
ulp/srp/kernel/srp_session.c
ulp/srp/kernel/srp_session.h

index 20cbf40..2f7308b 100644 (file)
 \r
 #include <complib/cl_math.h>\r
 \r
+#if DBG\r
+\r
+extern void* gp_session[SRP_MAX_SERVICE_ENTRIES];\r
+\r
+#endif\r
+\r
 /* __srp_create_cqs */\r
 /*!\r
 Creates the send/recv completion queues to be used by this connection\r
@@ -284,28 +290,11 @@ __srp_cm_dreq_cb(
        srp_hba_t       *p_hba = p_srp_session->p_hba;\r
        ib_cm_drep_t    cm_drep;\r
        ib_api_status_t status;\r
-       int             i;\r
-       int             retry_count = 0;\r
 \r
        SRP_ENTER( SRP_DBG_PNP );\r
 \r
-       SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
-               ("Target has issued a disconnect request.\n") );\r
-\r
-       if ( p_hba->adapter_paused == FALSE )\r
-       {\r
-               p_hba->adapter_paused = TRUE;\r
-               StorPortBusy( p_hba->p_ext, (ULONG)-1 );\r
-               StorPortCompleteRequest( p_hba->p_ext,\r
-                                                                SP_UNTAGGED,\r
-                                                                SP_UNTAGGED,\r
-                                                                SP_UNTAGGED,\r
-                                                                SRB_STATUS_BUSY );\r
-               SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG, ("Pausing Adapter for %s.\n", p_hba->ioc_info.profile.id_string) );\r
-       }\r
-\r
        cl_obj_lock( &p_srp_session->obj );\r
-       p_srp_session->connection.state = SRP_TARGET_DISCONNECTING;\r
+       p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
        cl_obj_unlock( &p_srp_session->obj );\r
 \r
        cm_drep.p_drep_pdata = NULL;\r
@@ -318,88 +307,14 @@ __srp_cm_dreq_cb(
                        ("Cannot respond to target disconnect request. Status = %d\n", status) );\r
        }\r
 \r
-       cl_obj_lock( &p_hba->obj );\r
-\r
-       for ( i = 0; i < SRP_MAX_SERVICE_ENTRIES; i++ )\r
-       {\r
-               if ( p_srp_session == p_hba->session_list[i] )\r
-               {\r
-                       p_hba->session_list[i] = NULL;\r
-                       break;\r
-               }\r
-       }\r
-\r
-       cl_obj_unlock( &p_hba->obj );\r
-\r
-       SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
-               ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );\r
-       cl_obj_destroy( &p_srp_session->obj );\r
-\r
-       do\r
-       {\r
-               retry_count++;\r
-\r
-               SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
-                       ("Attempting to reconnect %s. Connection Attempt Count = %d.\n",\r
-                        p_hba->ioc_info.profile.id_string,\r
-                        retry_count) );\r
-\r
-               SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
-                       ("Creating New Session For Service Entry Index %d.\n",\r
-                       p_hba->ioc_info.profile.num_svc_entries));\r
-               p_srp_session = srp_new_session(\r
-                       p_hba, &p_hba->p_svc_entries[i], &status );\r
-               if ( p_srp_session == NULL )\r
-               {\r
-                       status = IB_INSUFFICIENT_MEMORY;\r
-                       break;\r
-               }\r
-\r
-               SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
-                       ("New Session For Service Entry Index %d Created.\n",\r
-                       p_hba->ioc_info.profile.num_svc_entries));\r
-               SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
-                       ("Logging Into Session.\n"));\r
-               status = srp_session_login( p_srp_session );\r
-               if ( status == IB_SUCCESS )\r
-               {\r
-                       if ( p_hba->max_sg > p_srp_session->connection.max_scatter_gather_entries )\r
-                       {\r
-                               p_hba->max_sg = p_srp_session->connection.max_scatter_gather_entries;\r
-                       }\r
-\r
-                       if ( p_hba->max_srb_ext_sz > p_srp_session->connection.init_to_targ_iu_sz )\r
-                       {\r
-                               p_hba->max_srb_ext_sz =\r
-                                       sizeof( srp_send_descriptor_t ) -\r
-                                       SRP_MAX_IU_SIZE +\r
-                                       p_srp_session->connection.init_to_targ_iu_sz;\r
-                       }\r
-\r
-                       cl_obj_lock( &p_hba->obj );\r
-                       p_hba->session_list[i] = p_srp_session;\r
-                       cl_obj_unlock( &p_hba->obj );\r
-\r
-                       SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
-                               ("Session Login Issued Successfully.\n"));\r
-               }\r
-               else\r
-               {\r
-                       SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
-                               ("Session Login Failure Status = %d.\n", status));\r
-                       SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
-                                ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );\r
-                       cl_obj_destroy( &p_srp_session->obj );\r
-               }\r
-       } while ( (status != IB_SUCCESS) && (retry_count < 3) );\r
+       SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,\r
+               ("Target has issued a disconnect request for Session %d ref_cnt = %d.\n",\r
+                                               p_srp_session->target_id,\r
+                                               p_srp_session->obj.ref_cnt) );\r
 \r
-       if ( status == IB_SUCCESS )\r
+       if( !p_hba->adapter_stopped )\r
        {\r
-               SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
-                        ("Resuming Adapter for %s.\n", p_hba->ioc_info.profile.id_string) );\r
-               p_hba->adapter_paused = FALSE;\r
-               StorPortReady( p_hba->p_ext );\r
-//             StorPortNotification( BusChangeDetected, p_hba->p_ext, 0 );\r
+               srp_session_failed( p_srp_session );\r
        }\r
 \r
        SRP_EXIT( SRP_DBG_PNP );\r
@@ -443,22 +358,26 @@ __srp_cm_reply_cb(
 \r
        p_connection->request_limit      =\r
                MIN( get_srp_login_response_request_limit_delta( p_srp_login_rsp ), SRP_DEFAULT_RECV_Q_DEPTH );\r
+       \r
+       if( ib_ioc_profile_get_vend_id( &p_srp_session->p_hba->ioc_info.profile) == 0x00066a &&\r
+               cl_ntoh32( p_srp_session->p_hba->ioc_info.profile.subsys_id ) == 0x38 )\r
+       {\r
+               /* workaround for FVIC */\r
+               p_connection->request_limit /= 2;\r
+       }\r
 \r
+       p_connection->max_limit = p_connection->request_limit;\r
        p_connection->request_threashold = 2;\r
 #if DBG\r
        p_srp_session->x_req_limit = p_connection->request_limit;\r
 #endif\r
-       SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
-               ( "request_limit_delta %d, SRP_DEFAULT_RECV_Q_DEPTH %d, request_threashold %d\n", \r
-               get_srp_login_response_request_limit_delta( p_srp_login_rsp ), \r
-               SRP_DEFAULT_RECV_Q_DEPTH, p_connection->request_threashold ));\r
 \r
        p_connection->send_queue_depth   = p_connection->request_limit;\r
        p_connection->recv_queue_depth   = p_connection->request_limit;\r
        p_connection->init_to_targ_iu_sz = get_srp_login_response_max_init_to_targ_iu( p_srp_login_rsp );\r
        p_connection->targ_to_init_iu_sz = get_srp_login_response_max_targ_to_init_iu( p_srp_login_rsp );\r
 \r
-       p_connection->signaled_send_completion_count  = p_connection->send_queue_depth / 2;\r
+       p_connection->signaled_send_completion_count = 32;\r
        \r
        if (( p_connection->descriptor_format & DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS ) == DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS )\r
        {\r
@@ -735,9 +654,9 @@ __srp_issue_session_login(
 \r
        cm_req.init_depth = send_msg_depth;\r
 \r
-       cm_req.remote_resp_timeout = 15;\r
+       cm_req.remote_resp_timeout = ib_path_rec_pkt_life( p_connection->p_path_rec ) + 1;\r
        cm_req.flow_ctrl = FALSE;\r
-       cm_req.local_resp_timeout = 16;\r
+       cm_req.local_resp_timeout = ib_path_rec_pkt_life( p_connection->p_path_rec ) + 1;\r
        cm_req.retry_cnt = 1;\r
        cm_req.rnr_nak_timeout = 0; /* 655.36 ms */\r
        cm_req.rnr_retry_cnt = 6;\r
@@ -900,6 +819,13 @@ srp_connect(
                status = IB_ERROR;\r
                goto exit;\r
        }\r
+       \r
+       cl_thread_init( &p_session->recovery_thread, \r
+                                       (cl_pfn_thread_callback_t)srp_session_recovery_thread,\r
+                                       (void *)p_session, "srp_thread" );\r
+#if DBG\r
+       gp_session[p_session->target_id] = p_session;\r
+#endif\r
 \r
 exit:\r
        SRP_EXIT( SRP_DBG_PNP );\r
@@ -938,3 +864,4 @@ srp_free_connection(
 \r
 \r
 \r
+\r
index d9810f8..982a7b8 100644 (file)
@@ -80,6 +80,7 @@ typedef struct _srp_connection
 \r
        atomic32_t              tag;\r
        atomic32_t              request_limit;\r
+       atomic32_t                              max_limit;\r
        int32_t                 request_threashold;\r
        uint32_t                init_to_targ_iu_sz;\r
        uint32_t                targ_to_init_iu_sz;\r
index 98c243d..1dd7367 100644 (file)
@@ -210,6 +210,7 @@ __srp_process_session_send_completions(
        ib_api_status_t status;\r
        ib_wc_t         *p_wc_done_list = NULL;\r
        ib_wc_t         *p_wc;\r
+       BOOLEAN         to_recover = FALSE;\r
 \r
        SRP_ENTER( SRP_DBG_DATA );\r
 \r
@@ -231,7 +232,7 @@ __srp_process_session_send_completions(
                SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                        ("ib_poll_cq() failed!, status 0x%x\n", status) );\r
 \r
-               // TODO: Kill session and inform port driver link down scsiportnotification\r
+               p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
                cl_obj_unlock( &p_srp_session->obj );\r
                return;\r
        }\r
@@ -254,7 +255,8 @@ __srp_process_session_send_completions(
                        case IB_WCS_SUCCESS:\r
                                break;\r
                        case IB_WCS_WR_FLUSHED_ERR:\r
-                               // TODO: Kill session and inform port driver link down scsiportnotification\r
+                               if( !to_recover )\r
+                                       to_recover = TRUE;\r
                                SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
                                        ("Send Completion Status %s Vendore Status = 0x%x, \n",\r
                                        p_srp_session->p_hba->ifc.get_wc_status_str( p_wc->status ),\r
@@ -271,7 +273,7 @@ __srp_process_session_send_completions(
                                                   get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
                                break;\r
                        default:\r
-                               // TODO: Kill session and inform port driver link down scsiportnotification\r
+                               to_recover = TRUE;\r
                                SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                                        ("Send Completion Status %s Vendore Status = 0x%x, \n",\r
                                        p_srp_session->p_hba->ifc.get_wc_status_str( p_wc->status ),\r
@@ -299,6 +301,8 @@ __srp_process_session_send_completions(
                p_wc = p_wc_done_list;\r
        }\r
 \r
+       if( !to_recover )\r
+       {\r
        /* Re-arm the CQ for more completions */\r
        status = p_srp_session->p_hba->ifc.rearm_cq(\r
                p_srp_session->connection.h_send_cq, FALSE );\r
@@ -306,8 +310,13 @@ __srp_process_session_send_completions(
        {\r
                SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                        ("ib_rearm_cq() failed!, status 0x%x\n", status) );\r
-\r
-               // TODO: Kill session and inform port driver link down scsiportnotification\r
+                       p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+                       to_recover = TRUE;\r
+       }\r
+       }\r
+       if( to_recover == TRUE )\r
+       {\r
+               p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
        }\r
 \r
        cl_obj_deref( &p_srp_session->obj );\r
@@ -336,6 +345,14 @@ srp_send_completion_cb(
 \r
        __srp_process_session_send_completions( p_srp_session );\r
 \r
+       if( p_srp_session->connection.state == SRP_CONNECT_FAILURE )\r
+       {\r
+               if( !p_srp_session->p_hba->adapter_stopped )\r
+               {\r
+                       srp_session_failed( p_srp_session );\r
+               }\r
+       }\r
+\r
        SRP_EXIT( SRP_DBG_DATA );\r
 }\r
 \r
@@ -355,7 +372,7 @@ __srp_clean_send_descriptor(
        return status;\r
 }\r
 \r
-void\r
+ib_api_status_t\r
 __srp_post_io_request(\r
        IN      PVOID               p_dev_ext,\r
        IN OUT  PSCSI_REQUEST_BLOCK p_srb, \r
@@ -390,7 +407,7 @@ __srp_post_io_request(
 \r
                SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                                   ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, "\r
-                                  "Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+                                  "Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
                                   g_srb_status_name[p_srb->SrbStatus],\r
                                   p_srb->SrbStatus,\r
                                   g_srb_function_name[p_srb->Function],\r
@@ -413,16 +430,18 @@ __srp_post_io_request(
 \r
 exit:\r
        SRP_EXIT( SRP_DBG_DATA );\r
+       return status;\r
 }\r
 \r
 static \r
-void\r
+ib_api_status_t\r
 __srp_repost_io_request(\r
        IN      srp_session_t           *p_srp_session )\r
 {\r
        srp_hba_t               *p_hba;\r
        srp_send_descriptor_t   *p_send_descriptor = NULL;\r
        srp_descriptors_t       *p_descriptors = &p_srp_session->descriptors;\r
+       ib_api_status_t ib_status = IB_SUCCESS;\r
 \r
        SRP_ENTER( SRP_DBG_DATA );\r
 \r
@@ -463,13 +482,14 @@ __srp_repost_io_request(
                /* post the request */\r
                p_hba = p_srp_session->p_hba;\r
                p_send_descriptor = PARENT_STRUCT(p_list_item, srp_send_descriptor_t,list_item);\r
-               __srp_post_io_request( p_hba->p_ext, p_send_descriptor->p_srb, p_srp_session );\r
+               ib_status = __srp_post_io_request( p_hba->p_ext, p_send_descriptor->p_srb, p_srp_session );\r
        }\r
 \r
        cl_atomic_dec( &p_srp_session->repost_is_on );\r
 \r
 exit:\r
        SRP_EXIT( SRP_DBG_DATA );\r
+       return ib_status;\r
 }\r
        \r
 static inline void\r
@@ -500,6 +520,8 @@ __srp_process_recv_completion(
        srp_rsp_t               *p_srp_rsp;\r
        uint8_t                 response_status;\r
        srp_send_descriptor_t   *p_send_descriptor;\r
+       uint64_t                                response_tag;\r
+       BOOLEAN                                 session_recover = FALSE;\r
 \r
        SRP_ENTER( SRP_DBG_DATA );\r
 \r
@@ -508,10 +530,10 @@ __srp_process_recv_completion(
        set_srp_response_from_network_to_host( p_srp_rsp );\r
 \r
        response_status = get_srp_response_status( p_srp_rsp );\r
+       response_tag = get_srp_response_tag( (srp_rsp_t *)p_recv_descriptor->p_data_segment );\r
 \r
        p_send_descriptor = srp_find_matching_send_descriptor(\r
-               &p_srp_session->descriptors,\r
-               get_srp_response_tag( (srp_rsp_t *)p_recv_descriptor->p_data_segment ) );\r
+               &p_srp_session->descriptors, response_tag );\r
        if ( p_send_descriptor == NULL )\r
        {\r
                /* Repost the recv descriptor */\r
@@ -521,21 +543,27 @@ __srp_process_recv_completion(
                {\r
                        SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                                ("Failed to post send descriptor. Status = %d.\n", status) );\r
-                       // TODO: Kill session and inform port driver link down scsiportnotification\r
                }\r
-\r
+               else\r
+               {\r
                __srp_fix_request_limit( p_srp_session, p_srp_rsp );\r
-               __srp_repost_io_request( p_srp_session );\r
-\r
+               }\r
                SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
-                       ("Matching Send Descriptor Not Found.\n") );\r
+                       ("Matching Send Descriptor not Found: tag %#I64x\n", response_tag ) );\r
 \r
-               goto exit;\r
+               if( status == IB_SUCCESS &&\r
+                       !cl_qlist_count( &p_srp_session->descriptors.sent_descriptors ) )\r
+               {\r
+                       /* Seem all commands from sent queue were aborted by timeout already */\r
+                       /*      most likely Target get stuck. schedule session recovery */\r
+                       status = IB_ERROR;\r
+       }\r
+               return ( status );\r
        }\r
 \r
        SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
                           ("Recv Completion Received for Function = %s(0x%x), "\r
-                          "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+                          "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
                           g_srb_function_name[p_send_descriptor->p_srb->Function],\r
                           p_send_descriptor->p_srb->Function,\r
                           p_send_descriptor->p_srb->PathId,\r
@@ -551,7 +579,6 @@ __srp_process_recv_completion(
 \r
                        set_srp_tsk_mgmt_from_network_to_host( p_srp_tsk_mgmt );\r
 \r
-\r
                        if(response_status == SCSISTAT_GOOD)\r
                        {\r
                                p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_SUCCESS;\r
@@ -561,7 +588,7 @@ __srp_process_recv_completion(
                                p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;\r
                                SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
                                           ("Scsi Error  %s (%#x)  Received for Function = %s(0x%x), "\r
-                                          "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+                                          "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
                                           g_srb_scsi_status_name[response_status],\r
                                           response_status,\r
                                           g_srb_function_name[p_send_descriptor->p_srb->Function],\r
@@ -579,29 +606,13 @@ __srp_process_recv_completion(
                                        p_srp_session->connection.h_qp, &p_recv_descriptor->wr, NULL );\r
                                if ( status != IB_SUCCESS )\r
                                {\r
+                                       session_recover = TRUE;\r
                                        SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                                                ("Failed to post recv descriptor. Status = %d.\n", status) );\r
-                                       // TODO: Kill session and inform port driver link down storportnotification\r
                                }\r
 \r
-                               __srp_fix_request_limit( p_srp_session, p_srp_rsp );\r
-                               __srp_repost_io_request( p_srp_session );\r
-\r
-                               __srp_dump_srb_info( p_send_descriptor);\r
-\r
-                               status = __srp_clean_send_descriptor( p_send_descriptor, p_srp_session );\r
-                               if ( status != IB_SUCCESS )\r
-                               {\r
-                                       SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
-                                               ("Failed to unmap FMR  Status = %d.\n", status) );\r
-                                       // TODO: Kill session and inform port driver link down storportnotification\r
                                }\r
 \r
-                               StorPortNotification( RequestComplete, p_srp_session->p_hba->p_ext, p_send_descriptor->p_srb );\r
-                       }\r
-\r
-\r
-                       \r
                        break;\r
                }\r
 \r
@@ -616,7 +627,7 @@ __srp_process_recv_completion(
                                p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;\r
                                SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
                                           ("Scsi Error  %s (%#x)  Received for Function = %s(0x%x), "\r
-                                          "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+                                          "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
                                           g_srb_scsi_status_name[response_status],\r
                                           response_status,\r
                                           g_srb_function_name[p_send_descriptor->p_srb->Function],\r
@@ -676,7 +687,7 @@ __srp_process_recv_completion(
                                                                        p_send_descriptor->p_srb->SenseInfoBufferLength ) );\r
                                        SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
                                                        ("Sense Data  SENSE_KEY 0x%02x ADDITIONAL_SENSE_CODE"\r
-                                                       "0x%02x ADDITIONAL_SENSE_QUILIFIER 0x%02x.\n",\r
+                                                       "0x%02x ADDITIONAL_SENSE_QUALIFIER 0x%02x.\n",\r
                                                        p_sense_data[2],p_sense_data[12],p_sense_data[13]) );\r
                                        \r
                                        if ( ((p_sense_data[2]&0xf) == 0x0b /*ABORTED_COMMAND*/) &&\r
@@ -686,15 +697,19 @@ __srp_process_recv_completion(
                                        {\r
                                                /* probably a problem with the Vfx FC san like wire pull*/\r
                                                /* initiate session recovery */\r
+                                               session_recover = TRUE;\r
+                                               if( p_srp_session->p_hba->session_paused[p_srp_session->target_id] == FALSE )\r
+                                               {\r
+                                                       p_srp_session->p_hba->session_paused[p_srp_session->target_id] = TRUE;\r
                                                SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
                                                        ("Sense Data indicates FC link connectivity has been lost.\n") );\r
-                                               StorPortPauseDevice( p_srp_session->p_hba->p_ext,\r
-                                                                                        p_send_descriptor->p_srb->PathId,\r
-                                                                                        p_send_descriptor->p_srb->TargetId,\r
-                                                                                        p_send_descriptor->p_srb->Lun,\r
-                                                                                        5 );\r
+                                                       StorPortDeviceBusy( p_srp_session->p_hba->p_ext,\r
+                                                                                       SP_UNTAGGED,\r
+                                                                                       p_srp_session->target_id,\r
+                                                                                       SP_UNTAGGED,\r
+                                                                                       (ULONG)-1 );\r
                                        }\r
-                                       \r
+                               }\r
                                }\r
 \r
                                if ( get_srp_response_di_over( p_srp_rsp ) || get_srp_response_do_over( p_srp_rsp ) )\r
@@ -717,25 +732,11 @@ __srp_process_recv_completion(
                                p_srp_session->connection.h_qp, &p_recv_descriptor->wr, NULL );\r
                        if ( status != IB_SUCCESS )\r
                        {\r
+                               session_recover = TRUE;\r
                                SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                                        ("Failed to post recv descriptor. Status = %d.\n", status) );\r
-                               // TODO: Kill session and inform port driver link down storportnotification\r
                        }\r
 \r
-                       __srp_fix_request_limit( p_srp_session, p_srp_rsp );\r
-                       __srp_repost_io_request( p_srp_session );\r
-\r
-                       __srp_dump_srb_info( p_send_descriptor);\r
-\r
-                       status = __srp_clean_send_descriptor( p_send_descriptor, p_srp_session );\r
-                       if ( status != IB_SUCCESS )\r
-                       {\r
-                               SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
-                                       ("Failed to unmap FMR  Status = %d.\n", status) );\r
-                               // TODO: Kill session and inform port driver link down storportnotification\r
-                       }\r
-                       \r
-                       StorPortNotification( RequestComplete, p_srp_session->p_hba->p_ext, p_send_descriptor->p_srb );\r
                        break;\r
 \r
                case SRP_LOGIN_REQ:\r
@@ -743,11 +744,33 @@ __srp_process_recv_completion(
                case SRP_CRED_RSP:\r
                case SRP_AER_RSP:\r
                default:\r
-                       CL_ASSERT ( 0 );\r
+                       SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
+                               ("Illegal SRP IU CMD/RSP %#x received\n", \r
+                               get_srp_iu_buffer_type( (srp_iu_buffer_t *)p_send_descriptor->data_segment ) ) );\r
+                       session_recover = TRUE;\r
                        break;\r
        }\r
 \r
-exit:\r
+       status =  __srp_clean_send_descriptor( p_send_descriptor, p_srp_session );\r
+       if ( status != IB_SUCCESS )\r
+       {\r
+               session_recover = TRUE;\r
+       }\r
+\r
+       if( session_recover == TRUE )\r
+       {\r
+               status = IB_ERROR;\r
+       }\r
+       else \r
+       {\r
+               __srp_fix_request_limit( p_srp_session, p_srp_rsp );\r
+               status = __srp_repost_io_request( p_srp_session );\r
+       }\r
+\r
+       __srp_dump_srb_info( p_send_descriptor);\r
+\r
+       StorPortNotification( RequestComplete, p_srp_session->p_hba->p_ext, p_send_descriptor->p_srb );\r
+\r
        SRP_EXIT( SRP_DBG_DATA );\r
 \r
        return ( status );\r
@@ -782,7 +805,8 @@ __srp_process_session_recv_completions(
                SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                        ("ib_poll_cq() failed!, status 0x%x\n", status) );\r
 \r
-               // TODO: Kill session and inform port driver link down scsiportnotification\r
+               p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+\r
                SRP_EXIT( SRP_DBG_DATA );\r
                cl_obj_unlock( &p_srp_session->obj );\r
                return;\r
@@ -806,7 +830,9 @@ __srp_process_session_recv_completions(
                        status = __srp_process_recv_completion( p_recv_descriptor, p_srp_session );\r
                        if ( status != IB_SUCCESS )\r
                        {\r
-                               // TODO: Kill session and inform port driver link down scsiportnotification\r
+                               p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+                               cl_obj_deref( &p_srp_session->obj );\r
+                               return;\r
                        }\r
                }\r
                else\r
@@ -825,6 +851,10 @@ __srp_process_session_recv_completions(
                                        p_srp_session->p_hba->ifc.get_wc_status_str( p_wc->status )));\r
 \r
                        }\r
+\r
+                       p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+                       cl_obj_deref( &p_srp_session->obj );\r
+                       return;\r
                }\r
 \r
                /* Put onto head of free list */\r
@@ -844,8 +874,10 @@ __srp_process_session_recv_completions(
        {\r
                SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                        ("ib_rearm_cq() failed!, status 0x%x\n", status) );\r
+               p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
 \r
-               // TODO: Kill session and inform port driver link down scsiportnotification\r
+               cl_obj_deref( &p_srp_session->obj );\r
+               return;\r
        }\r
 \r
        cl_obj_deref( &p_srp_session->obj );\r
@@ -873,7 +905,10 @@ srp_recv_completion_cb(
        UNUSED_PARAM( h_cq );\r
 \r
        __srp_process_session_recv_completions( p_srp_session );\r
-\r
+       if( p_srp_session->connection.state == SRP_CONNECT_FAILURE )\r
+       {\r
+               srp_session_failed( p_srp_session );\r
+       }\r
        SRP_EXIT( SRP_DBG_DATA );\r
 }\r
 \r
@@ -887,7 +922,7 @@ Build the SRP Cmd to be sent to the VFx target
 @return - none\r
 */\r
 static inline\r
-void\r
+BOOLEAN\r
 __srp_build_cmd(\r
        IN      PVOID               p_dev_ext,\r
        IN OUT  PSCSI_REQUEST_BLOCK p_srb,\r
@@ -1124,6 +1159,7 @@ __srp_build_cmd(
        //set_srp_command_from_host_to_network( p_srp_cmd );\r
 \r
        SRP_EXIT( SRP_DBG_DATA );\r
+       return TRUE;\r
 }\r
 \r
 /* srp_format_io_request */\r
@@ -1159,7 +1195,9 @@ srp_format_io_request(
 \r
        p_srp_session = p_hba->session_list[p_srb->TargetId];\r
 \r
-       if ( p_srp_session != NULL )\r
+       if ( p_srp_session != NULL && \r
+                p_srp_session->connection.state == SRP_CONNECTED &&\r
+                !p_hba->session_paused[p_srb->TargetId] )\r
        {\r
                srp_conn_info_t srp_conn_info;\r
 \r
@@ -1180,19 +1218,24 @@ srp_format_io_request(
 \r
                srp_build_send_descriptor( p_dev_ext, p_srb, &srp_conn_info );\r
 \r
-               __srp_build_cmd( p_dev_ext, p_srb, &srp_conn_info );\r
+               result = __srp_build_cmd( p_dev_ext, p_srb, &srp_conn_info );\r
+               \r
+               if( result != TRUE )\r
+                       SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
+                               ("BUILD command %#x failed = %#x tag %#I64x\n",\r
+                               p_srb->Cdb[0], p_srb->SrbStatus, srp_conn_info.tag ) );\r
        }\r
        else\r
        {\r
                // Handle the error case here\r
                SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                        ("Cannot Find Session For Target ID = %d\n", p_srb->TargetId) );\r
-               cl_obj_unlock( &p_hba->obj );\r
+\r
                p_srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;\r
+               cl_obj_unlock( &p_hba->obj );\r
                result = FALSE;\r
        }\r
 \r
-\r
        SRP_EXIT( SRP_DBG_DATA );\r
        return ( result );\r
 }\r
@@ -1214,7 +1257,15 @@ srp_post_io_request(
 \r
        p_srp_session = p_hba->session_list[p_srb->TargetId];\r
 \r
-       if ( p_srp_session != NULL )\r
+       if( p_hba->session_paused[p_srb->TargetId] == TRUE )\r
+       {\r
+               cl_obj_unlock( &p_hba->obj );\r
+               p_srb->SrbStatus = SRB_STATUS_BUSY;\r
+               goto err;\r
+       }\r
+\r
+       if ( p_srp_session != NULL && \r
+                p_srp_session->connection.state == SRP_CONNECTED )\r
        {\r
                cl_obj_ref( &p_srp_session->obj );\r
                cl_obj_unlock( &p_hba->obj );\r
@@ -1226,14 +1277,26 @@ srp_post_io_request(
                        !cl_is_qlist_empty( &p_descriptors->pending_descriptors ) ||\r
                        p_srp_session->repost_is_on )\r
                {\r
+                       int32_t num_pending_desc = (int32_t)cl_qlist_count( &p_descriptors->pending_descriptors );\r
                        cl_spinlock_release ( &p_descriptors->pending_list_lock );\r
                        srp_add_pending_descriptor( p_descriptors, p_send_descriptor );\r
+                       \r
+                       /* don't allow pending queue grow indefinitely */\r
+                       if( num_pending_desc >= p_srp_session->connection.max_limit )\r
+                       {               \r
+                               StorPortDeviceBusy( p_dev_ext, \r
+                                                                       p_srb->PathId,\r
+                                                                       p_srb->TargetId,\r
+                                                                       p_srb->Lun,\r
+                                                                       1 );\r
+                       }\r
+\r
                        cl_obj_deref( &p_srp_session->obj );\r
                        goto exit;\r
                }\r
                cl_spinlock_release ( &p_descriptors->pending_list_lock );\r
 \r
-               __srp_post_io_request( p_dev_ext, p_srb, p_srp_session );\r
+               status = __srp_post_io_request( p_dev_ext, p_srb, p_srp_session );\r
                cl_obj_deref( &p_srp_session->obj );\r
                goto exit;\r
        }\r
@@ -1247,7 +1310,7 @@ srp_post_io_request(
 err:\r
        SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
                           ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, "\r
-                          "Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+                          "Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
                           g_srb_status_name[p_srb->SrbStatus],\r
                           p_srb->SrbStatus,\r
                           g_srb_function_name[p_srb->Function],\r
@@ -1268,6 +1331,11 @@ err:
        StorPortNotification( RequestComplete, p_dev_ext, p_srb );\r
 \r
 exit:\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+               srp_session_failed( p_srp_session );\r
+       }\r
        SRP_EXIT( SRP_DBG_DATA );\r
 }\r
 \r
@@ -1501,7 +1569,8 @@ srp_x_clean(
 {\r
        srp_session_t           *p_srp_session = p_session;\r
 \r
-       if (p_srp_session == NULL)\r
+       if (p_srp_session == NULL ||\r
+               p_srp_session->connection.state != SRP_CONNECTED )\r
                return;\r
 \r
        p_srp_session->x_pkt_fmr = 0;\r
@@ -1524,7 +1593,8 @@ srp_x_print(
 {\r
        srp_session_t           *p_srp_session = p_session;\r
 \r
-       if (p_srp_session == NULL)\r
+       if (p_srp_session == NULL || \r
+               p_srp_session->connection.state != SRP_CONNECTED )\r
                return;\r
 \r
        SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_DATA,\r
index c5d893a..14f5167 100644 (file)
@@ -265,7 +265,7 @@ void
 srp_x_clean(\r
        IN      void            *p_session );\r
 \r
-void *gp_session = NULL;\r
+void* gp_session[SRP_MAX_SERVICE_ENTRIES];\r
 \r
 #endif\r
 \r
@@ -548,7 +548,7 @@ srp_dispatch_pnp(
                        ("KeReleaseMutex status = %d.\n", release_status) );\r
        }\r
 \r
-       #if DBG\r
+       #if DBG_STATISTICS\r
        /* statistics */\r
 \r
        /* this function is called sometimes in the begging of the test with \r
@@ -557,11 +557,14 @@ srp_dispatch_pnp(
                /* sometimes it's called once in 50msec, so we'll print once in 20 times */\r
                static int interval = 40; /* 2 sec */\r
                static int cnt = 0;\r
+               static int i;\r
                if (++cnt >= interval)\r
                {\r
                        cnt = 0;\r
-                       srp_x_print( gp_session );\r
-                       srp_x_clean( gp_session );\r
+                       if(i > 3 ) i = 0;\r
+                       srp_x_print( gp_session[i] );\r
+                       srp_x_clean( gp_session[i] );\r
+                       i++;\r
                }\r
        }\r
        \r
@@ -712,24 +715,13 @@ srp_start_io(
 \r
                        if ( (p_srb->Lun == 0) && (p_srp_session != NULL) )\r
                        {\r
-                               p_hba->session_list[p_srb->TargetId] = NULL;\r
-\r
-                               CL_ASSERT( p_srp_session != NULL );\r
-\r
                                p_srp_session->p_shutdown_srb = p_srb;\r
-                               cl_obj_destroy( &p_srp_session->obj );\r
 \r
-                               SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
-                                                  ("Returning SrbStatus %s(0x%x) for "\r
-                                                  "Function = %s(0x%x), Path = 0x%x, "\r
-                                                  "Target = 0x%x, Lun = 0x%x\n",\r
-                                                  g_srb_status_name[p_srb->SrbStatus],\r
-                                                  p_srb->SrbStatus,\r
-                                                  g_srb_function_name[p_srb->Function],\r
-                                                  p_srb->Function,\r
-                                                  p_srb->PathId,\r
-                                                  p_srb->TargetId,\r
-                                                  p_srb->Lun) );\r
+                               if( !p_hba->adapter_stopped )\r
+                               {\r
+                                       p_hba->adapter_stopped = TRUE;\r
+                                       srp_disconnect_sessions( p_hba );\r
+                               }\r
                        }\r
                        else\r
                        {\r
@@ -831,8 +823,9 @@ srp_reset(
        SRP_ENTER( SRP_DBG_PNP );\r
 \r
        UNUSED_PARAM( p_dev_ext );\r
-       UNUSED_PARAM( path_id );\r
 \r
+       StorPortCompleteRequest( p_dev_ext, (UCHAR)path_id, SP_UNTAGGED, SP_UNTAGGED, SRB_STATUS_NO_HBA );\r
+       \r
        SRP_EXIT( SRP_DBG_PNP );\r
        return FALSE;\r
 }\r
@@ -873,6 +866,9 @@ srp_adapter_ctrl(
                {\r
                        SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
                                ("HBA Object ref_cnt = %d\n", p_ext->p_hba->obj.ref_cnt) );\r
+                       if( !p_ext->p_hba->adapter_stopped )\r
+                               p_ext->p_hba->adapter_stopped = TRUE;\r
+                       srp_disconnect_sessions( p_ext->p_hba );\r
                        cl_obj_destroy( &p_ext->p_hba->obj );\r
                        p_ext->p_hba = NULL;\r
                }\r
index 09d69c4..6336a49 100644 (file)
@@ -730,29 +730,29 @@ __srp_connect_sessions(
        {\r
                int     retry_count = 0;\r
 \r
-               SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
-                       ("Creating New Session For Service Entry Index %d.\n",\r
-                       p_hba->ioc_info.profile.num_svc_entries));\r
-\r
-               p_session = srp_new_session(\r
-                       p_hba, &p_hba->p_svc_entries[i], &status );\r
-               if( p_session == NULL )\r
-               {\r
-                       status = IB_INSUFFICIENT_MEMORY;\r
-                       continue;\r
-               }\r
+               do{\r
+                       retry_count++;\r
 \r
-               SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
-                       ("New Session For Service Entry Index %d Created.\n",\r
-                       p_hba->ioc_info.profile.num_svc_entries));\r
+                       SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
+                       ("Creating New Session For Service Entry Index %d.\n", i ));\r
+\r
+                       p_session = srp_new_session(\r
+                                                       p_hba, \r
+                                                       &p_hba->p_svc_entries[i],\r
+                                                       &p_hba->p_srp_path_record->path_rec,\r
+                                                       &status );\r
+                       if( p_session == NULL )\r
+                       {\r
+                               status = IB_INSUFFICIENT_MEMORY;\r
+                               break;\r
+                       }\r
 \r
-               do\r
-               {\r
-                       retry_count++;\r
+                       SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
+                       ("New Session For Service Entry Index %d Created.\n", i ));\r
 \r
                        SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
-                               ("Attempting to connect %s. Connection Attempt Count = %d.\n",\r
-                                p_hba->ioc_info.profile.id_string,\r
+                               ("Attempting to connect %s. Svc Idx %d; Connection Attempt Count = %d.\n", \r
+                                p_hba->ioc_info.profile.id_string, i,\r
                                 retry_count) );\r
                        SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
                                ("Logging Into Session.\n"));\r
@@ -761,23 +761,10 @@ __srp_connect_sessions(
                        {\r
                                any_ioc_connected = TRUE;\r
 \r
-                               if ( (p_hba->max_sg >\r
-                                       p_session->connection.max_scatter_gather_entries)\r
-                                       && !(p_session->connection.descriptor_format &\r
-                                       DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS) )\r
-                               {\r
-                                       p_hba->max_sg = p_session->connection.max_scatter_gather_entries;\r
-                               }\r
-\r
-                               if ( p_hba->max_srb_ext_sz > p_session->connection.init_to_targ_iu_sz )\r
-                               {\r
-                                       p_hba->max_srb_ext_sz =\r
-                                               sizeof( srp_send_descriptor_t ) -\r
-                                               SRP_MAX_IU_SIZE +\r
-                                               p_session->connection.init_to_targ_iu_sz;\r
-                               }\r
+                               srp_session_adjust_params( p_session );\r
 \r
                                cl_obj_lock( &p_hba->obj );\r
+                               p_session->target_id = (UCHAR)i;\r
                                p_hba->session_list[i] = p_session;\r
                                cl_obj_unlock( &p_hba->obj );\r
 \r
@@ -787,29 +774,32 @@ __srp_connect_sessions(
                        else\r
                        {\r
                                SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_PNP,\r
-                                       ("Session Login Failure Status = %d.\n", status));\r
+                                       ("Session Login for Service Idx %d Failure Status = %d.\n", i, status));\r
+                               cl_obj_destroy( &p_session->obj );\r
                        }\r
+\r
                } while ( (status != IB_SUCCESS) && (retry_count < 3) );\r
 \r
-               if( status != IB_SUCCESS )\r
-               {\r
-                       SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
-                               ("Session Object ref_cnt = %d\n", p_session->obj.ref_cnt) );\r
-                       cl_obj_destroy( &p_session->obj );\r
-               }\r
        }\r
 \r
        if ( any_ioc_connected == TRUE )\r
        {\r
                status = IB_SUCCESS;\r
-               if ( p_hba->adapter_paused == TRUE )\r
+               for( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
                {\r
-                       SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
-                               ("Resuming Adapter for %s.\n",\r
-                               p_hba->ioc_info.profile.id_string) );\r
-                       p_hba->adapter_paused = FALSE;\r
-                       StorPortReady( p_hba->p_ext );\r
-                       //StorPortNotification( BusChangeDetected, p_hba->p_ext, 0 );\r
+                       p_session = p_hba->session_list[i];\r
+                       \r
+                       if( p_session != NULL &&\r
+                               p_session->connection.state == SRP_CONNECTED && \r
+                               p_hba->session_paused[i] == TRUE )\r
+                       {\r
+                               SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
+                               ("Resuming Adapter Session %d for %s.\n", i,\r
+                                               p_hba->ioc_info.profile.id_string) );\r
+\r
+                               p_hba->session_paused[i] = FALSE;\r
+                               StorPortDeviceReady( p_hba->p_ext, SP_UNTAGGED, (UCHAR)i, SP_UNTAGGED );\r
+                       }\r
                }\r
        }\r
 \r
@@ -818,10 +808,9 @@ __srp_connect_sessions(
        return status;\r
 }\r
 \r
-static void\r
-__srp_disconnect_sessions(\r
-       IN                              srp_hba_t                                       *p_hba,\r
-       IN                              BOOLEAN                                         pause_adapter )\r
+void\r
+srp_disconnect_sessions(\r
+       IN                              srp_hba_t                                       *p_hba )\r
 {\r
        uint32_t                i;\r
        srp_session_t   *p_session;\r
@@ -834,72 +823,15 @@ __srp_disconnect_sessions(
        {\r
                if ( p_hba->session_list[i] != NULL )\r
                {\r
-                       break;\r
+                       p_session = p_hba->session_list[i];\r
+                       p_hba->session_list[i] = NULL;\r
+                       p_session->connection.state = SRP_CONNECT_FAILURE;\r
+                       srp_session_failed( p_session );\r
                }\r
        }\r
 \r
        cl_obj_unlock( &p_hba->obj );\r
 \r
-       if ( i == p_hba->ioc_info.profile.num_svc_entries )\r
-       {\r
-               SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
-                       ("No current connections to %s.\n",\r
-                       p_hba->ioc_info.profile.id_string) );\r
-               goto exit;\r
-       }\r
-\r
-       SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
-               ("Current path to %s has been lost.\n",\r
-               p_hba->ioc_info.profile.id_string) );\r
-\r
-       p_hba->p_srp_path_record = NULL;\r
-\r
-       if ( pause_adapter == TRUE )\r
-       {\r
-               if ( p_hba->adapter_paused == FALSE )\r
-               {\r
-                       p_hba->adapter_paused = TRUE;\r
-                       StorPortBusy( p_hba->p_ext, (ULONG)-1 );\r
-                       StorPortCompleteRequest( p_hba->p_ext,\r
-                                                                        SP_UNTAGGED,\r
-                                                                        SP_UNTAGGED,\r
-                                                                        SP_UNTAGGED,\r
-                                                                        SRB_STATUS_BUSY );\r
-                       SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
-                               ("Pausing Adapter for %s.\n",\r
-                               p_hba->ioc_info.profile.id_string) );\r
-               }\r
-       }\r
-\r
-       /* Destroy all the connections. */\r
-       SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
-               ("Destroy all connections to %s.\n",\r
-               p_hba->ioc_info.profile.id_string) );\r
-\r
-       for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
-       {\r
-               cl_obj_lock( &p_hba->obj );\r
-               p_session = p_hba->session_list[i];\r
-               p_hba->session_list[i] = NULL;\r
-               cl_obj_unlock( &p_hba->obj );\r
-\r
-               if ( p_session != NULL )\r
-               {\r
-                       SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
-                               ("Session Object ref_cnt = %d\n", p_session->obj.ref_cnt) );\r
-                       __srp_cleanup_session ( &p_session->obj );\r
-                       cl_obj_destroy( &p_session->obj );\r
-               }\r
-               else\r
-               {\r
-                       SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,\r
-                               ("Session for Target ID %d on %s is NULL.\n",\r
-                                i,\r
-                                p_hba->ioc_info.profile.id_string) ); // <-- OK in a shutdown or target disconnect\r
-               }\r
-       }\r
-\r
-exit:\r
        SRP_EXIT( SRP_DBG_PNP );\r
 }\r
 \r
@@ -1040,11 +972,16 @@ __srp_pnp_cb(
 \r
                        SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
                                ("Hey!!! Our IOC went away.\n") );\r
-\r
-                       __srp_disconnect_sessions( p_hba, FALSE );\r
+                       \r
+                       if( !p_hba->adapter_stopped )\r
+                               p_hba->adapter_stopped = TRUE;\r
+                       \r
+                       srp_disconnect_sessions( p_hba );\r
                        __srp_remove_path_records( p_hba );\r
+\r
                        SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
-                               ("HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
+                               ("IB_PNP_IOC_REMOVE HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt ) );\r
+\r
                        break;\r
 \r
                case IB_PNP_IOC_PATH_ADD:\r
@@ -1068,6 +1005,9 @@ __srp_pnp_cb(
                                        p_hba->ioc_info.profile.id_string) );\r
                                status = __srp_connect_path( p_hba );\r
                        }\r
+\r
+                       SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
+                               (" IOC_PATH ADD HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt ) );\r
                        break;\r
 \r
                case IB_PNP_IOC_PATH_REMOVE:\r
@@ -1088,12 +1028,7 @@ __srp_pnp_cb(
 \r
                                        if ( g_srp_system_shutdown == FALSE )\r
                                        {\r
-                                               __srp_disconnect_sessions( p_hba, TRUE );\r
-                                               status = __srp_connect_path( p_hba );\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               __srp_disconnect_sessions( p_hba, FALSE );\r
+                                               srp_disconnect_sessions( p_hba );\r
                                        }\r
                                }\r
 \r
index 96d9e3d..86d3238 100644 (file)
@@ -74,13 +74,13 @@ typedef struct _srp_hba
        srp_path_record_t               *p_srp_path_record;\r
        cl_qlist_t                              path_record_list;\r
        cl_spinlock_t                   path_record_list_lock;\r
-       BOOLEAN                                 adapter_paused;\r
+       BOOLEAN                                 adapter_stopped;\r
 \r
        uint32_t                                max_sg;\r
        uint32_t                                max_srb_ext_sz;\r
-\r
        /* List of sessions     indexed by target id */\r
        p_srp_session_t                 session_list[SRP_MAX_SERVICE_ENTRIES];\r
+       BOOLEAN                                 session_paused[SRP_MAX_SERVICE_ENTRIES];\r
 }      srp_hba_t;\r
 \r
 \r
@@ -93,4 +93,8 @@ srp_hba_create(
        IN                              cl_obj_t* const                         p_drv_obj,\r
                OUT                     struct _srp_ext* const          p_ext );\r
 \r
+void\r
+srp_disconnect_sessions(\r
+       IN                              srp_hba_t                                       *p_hba );\r
+\r
 #endif /* _SRP_HBA_H_ */\r
index 502e4d7..0f547d5 100644 (file)
 #include "srp_session.h"\r
 #include <stdlib.h>\r
 \r
-#if DBG\r
-extern void *gp_session;\r
-#endif\r
-\r
 /* __srp_destroying_session */\r
 /*!\r
 Called when session has been marked for destruction\r
@@ -230,6 +226,8 @@ Allocates and initializes a session structure and it's sub-structures
 @param p_hba       - pointer to the hba associated with the new session\r
 @param ioc_guid    - pointer to the target's ioc guid\r
 @param p_svc_entry - pointer to the service entry\r
+@param p_path_rec  - pointer to path record to use.\r
+\r
 @param p_status    - pointer to the reason code\r
 \r
 @return - Pointer to new session or NULL if failure. See p_status for reason code.\r
@@ -238,6 +236,7 @@ srp_session_t*
 srp_new_session(\r
        IN      srp_hba_t       *p_hba,\r
        IN      ib_svc_entry_t  *p_svc_entry,\r
+       IN      ib_path_rec_t   *p_path_rec,\r
        OUT     ib_api_status_t *p_status )\r
 {\r
        uint64_t                                target_id_extension;\r
@@ -252,6 +251,11 @@ srp_new_session(
                goto exit;\r
        }\r
 \r
+       if( p_path_rec == NULL )\r
+       {\r
+               goto exit;\r
+       }\r
+\r
        p_srp_session = (srp_session_t*)cl_zalloc( sizeof(srp_session_t) );\r
        if ( p_srp_session == NULL )\r
        {\r
@@ -267,8 +271,8 @@ srp_new_session(
                                                                        &p_hba->ioc_info.profile,\r
                                                                        p_hba->info.ca_guid,\r
                                                                        target_id_extension,\r
-                                                                        &p_hba->p_srp_path_record->path_rec,\r
-                                                                        p_svc_entry->id );\r
+                                                                       p_path_rec,\r
+                                                                       p_svc_entry->id );\r
        if ( *p_status != IB_SUCCESS )\r
        {\r
                cl_free( p_srp_session );\r
@@ -306,11 +310,6 @@ srp_new_session(
        SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
                ("After Insert Rel Session Object ref_cnt = %d\n",\r
                p_srp_session->obj.ref_cnt) );\r
-\r
-#if DBG\r
-       gp_session = p_srp_session;\r
-#endif\r
-\r
 exit:\r
        SRP_EXIT( SRP_DBG_SESSION );\r
 \r
@@ -348,13 +347,243 @@ srp_session_login(
                                                  (uint8_t)p_srp_session->p_hba->ioc_info.profile.send_msg_depth,\r
                                                  p_srp_session );\r
 \r
-       if ( status != IB_SUCCESS )\r
-       { // clean resources, taken upon login\r
-               srp_close_ca( &p_srp_session->hca );\r
-               srp_destroy_descriptors( &p_srp_session->descriptors );\r
-       }\r
-\r
 exit:\r
        SRP_EXIT( SRP_DBG_SESSION );\r
        return ( status );\r
 }\r
+\r
+void\r
+srp_session_failed(\r
+IN             srp_session_t*  p_srp_session )\r
+{\r
+\r
+       SRP_ENTER( SRP_DBG_SESSION );\r
+       \r
+       if( !p_srp_session )\r
+               return;\r
+\r
+       cl_obj_lock( &p_srp_session->obj );\r
+       \r
+       if( p_srp_session->obj.state != CL_INITIALIZED )\r
+       {\r
+               cl_obj_unlock( &p_srp_session->obj );\r
+               return;\r
+       }\r
+       \r
+       if( p_srp_session->connection.state != SRP_CONNECT_FAILURE )\r
+       {\r
+               cl_obj_unlock( &p_srp_session->obj );\r
+               return;\r
+       }\r
+       p_srp_session->connection.state = SRP_CONNECTION_CLOSING;\r
+       \r
+       cl_obj_unlock( &p_srp_session->obj );\r
+\r
+       SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+               ("Session Idx %d failed\n", p_srp_session->target_id ) );\r
+\r
+       cl_event_signal( &p_srp_session->offload_event );\r
+}\r
+\r
+ib_api_status_t\r
+srp_session_connect( \r
+  IN           srp_hba_t                       *p_hba,\r
+  IN OUT       p_srp_session_t         *pp_srp_session,\r
+  IN           UCHAR                           svc_idx )\r
+{\r
+       ib_api_status_t         ib_status;\r
+       srp_path_record_t       *p_srp_path_rec;\r
+       srp_session_t           *p_session;\r
+       uint64_t                                target_id_extension;\r
+\r
+       SRP_ENTER( SRP_DBG_SESSION );\r
+       \r
+       if( *pp_srp_session != NULL )\r
+       {\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
+       if( !cl_qlist_count( &p_hba->path_record_list ) )\r
+       {\r
+               cl_spinlock_release( &p_hba->path_record_list_lock );\r
+               return IB_NOT_FOUND;\r
+       }\r
+\r
+       p_srp_path_rec = (srp_path_record_t *)cl_qlist_head( &p_hba->path_record_list );\r
+       \r
+       cl_spinlock_release( &p_hba->path_record_list_lock );\r
+\r
+       if( p_srp_path_rec == (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
+       {\r
+               return IB_NOT_FOUND;\r
+       }\r
+\r
+       ib_status = __srp_validate_service_entry( &p_hba->p_svc_entries[svc_idx], &target_id_extension );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_SESSION,\r
+                       ("Failed validate service entry status %x\n", ib_status ));\r
+               return ib_status;\r
+       }\r
+       \r
+       p_session = srp_new_session( p_hba,\r
+                                       &p_hba->p_svc_entries[svc_idx],\r
+                                       &p_srp_path_rec->path_rec,\r
+                                       &ib_status );\r
+       \r
+       if( ib_status != IB_SUCCESS || p_session == NULL )\r
+       {\r
+               SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_SESSION,\r
+                       ("Failed create Session for SVC idx %d status %x\n", svc_idx, ib_status ));\r
+               \r
+               *pp_srp_session = NULL;\r
+               \r
+               return ib_status;\r
+       }\r
+\r
+       ib_status = srp_session_login( p_session );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_SESSION,\r
+                       ("Failed Session Login status %x\n", ib_status ));\r
+\r
+               *pp_srp_session = NULL;\r
+               \r
+               cl_obj_destroy( &p_session->obj );\r
+               \r
+               return ib_status;\r
+       }\r
+       srp_session_adjust_params( p_session );\r
+\r
+       cl_obj_lock( &p_hba->obj );\r
+\r
+       p_session->target_id = svc_idx;\r
+\r
+       *pp_srp_session = p_session;\r
+\r
+       cl_obj_unlock( &p_hba->obj );\r
+\r
+\r
+       SRP_EXIT( SRP_DBG_SESSION );\r
+       return ib_status;\r
+}\r
+\r
+void\r
+srp_session_adjust_params( \r
+       IN      srp_session_t   *p_session )\r
+{\r
+\r
+       if ( ( p_session->p_hba->max_sg > p_session->connection.max_scatter_gather_entries )\r
+               && !( p_session->connection.descriptor_format & DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS) )\r
+       {\r
+               p_session->p_hba->max_sg = p_session->connection.max_scatter_gather_entries;\r
+       }\r
+\r
+       if ( p_session->p_hba->max_srb_ext_sz > p_session->connection.init_to_targ_iu_sz )\r
+       {\r
+               p_session->p_hba->max_srb_ext_sz =\r
+                       sizeof( srp_send_descriptor_t ) -\r
+                       SRP_MAX_IU_SIZE +\r
+                       p_session->connection.init_to_targ_iu_sz;\r
+       }\r
+}\r
+\r
+static void\r
+__srp_session_recovery(\r
+IN             srp_session_t*          p_failed_session , \r
+IN             BOOLEAN                         reconnect_request )\r
+{\r
+       ib_api_status_t ib_status;\r
+       srp_hba_t*              p_hba;\r
+       srp_session_t*  p_new;\r
+       srp_session_t*  p_old;\r
+       UCHAR                   target_id;\r
+       int                             retry_count;\r
+\r
+       SRP_ENTER( SRP_DBG_SESSION );\r
+       \r
+       if( !p_failed_session )\r
+               return;\r
+       if ( ( p_hba = p_failed_session->p_hba ) == NULL )\r
+               return;\r
+\r
+       p_old = p_failed_session;\r
+       target_id = p_old->target_id;\r
+       p_hba->session_list[target_id] = NULL;\r
+\r
+       if( !reconnect_request )\r
+       {\r
+               /* we're done here */\r
+               SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+                       ("Session Id: %d won't recover\n", p_old->target_id ) );\r
+               cl_obj_destroy( &p_old->obj );\r
+               return;\r
+       }\r
+\r
+       if( !p_hba->session_paused[target_id] )\r
+       {\r
+               p_hba->session_paused[target_id] = TRUE;\r
+\r
+               StorPortDeviceBusy( p_hba->p_ext,\r
+                                       SP_UNTAGGED,\r
+                                       target_id,\r
+                                       SP_UNTAGGED, \r
+                                       (ULONG)-1 );\r
+       }\r
+\r
+       SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+               ("Pausing Adapter Session %d\n", target_id ) );\r
+\r
+       cl_obj_destroy( &p_old->obj );\r
+\r
+       for( retry_count=0; retry_count < 3 ; retry_count++ )\r
+       {\r
+               ib_status = srp_session_connect( p_hba, &p_new, target_id );\r
+\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+                               ("Failed session idx %d connect\n", target_id ) );\r
+               \r
+                       continue;\r
+               }\r
+\r
+               p_hba->session_list[target_id] = p_new;\r
+\r
+               SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+                               ("Session idx %d connected. Resuming\n", target_id ) );\r
+\r
+               StorPortDeviceReady( p_hba->p_ext,\r
+                                               SP_UNTAGGED,\r
+                                               target_id,\r
+                                               SP_UNTAGGED );\r
+\r
+               p_hba->session_paused[target_id] = FALSE;\r
+               \r
+               return;\r
+       }\r
+\r
+       /* what do we do now ? */\r
+       SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+                       ("Session idx %d recovery failed\n", target_id) );\r
+\r
+       return;\r
+}\r
+\r
+void\r
+srp_session_recovery_thread(\r
+       IN              void*    const          context )\r
+{\r
+       srp_session_t*  p_session = (srp_session_t *)context;\r
+       cl_status_t             status;\r
+\r
+       if( p_session == NULL )\r
+               return;\r
+\r
+       cl_event_init( &p_session->offload_event, FALSE);\r
+\r
+       status = cl_event_wait_on( &p_session->offload_event, EVENT_NO_TIMEOUT, FALSE );\r
+\r
+       __srp_session_recovery( p_session,  !p_session->p_hba->adapter_stopped );\r
+}\r
index 925ab68..a0ee036 100644 (file)
@@ -58,6 +58,11 @@ typedef struct _srp_session
 \r
        SCSI_REQUEST_BLOCK  *p_shutdown_srb;\r
 \r
+       /* keep session level SCSI address */\r
+       UCHAR                           target_id;\r
+       cl_event_t                      offload_event;\r
+       cl_thread_t                     recovery_thread;\r
+\r
 #if DBG\r
        /* statistics */\r
 \r
@@ -95,6 +100,7 @@ srp_session_t*
 srp_new_session(\r
        IN      srp_hba_t       *p_hba,\r
        IN      ib_svc_entry_t  *p_svc_entry,\r
+       IN      ib_path_rec_t   *p_path_rec,\r
        OUT     ib_api_status_t *p_status );\r
 \r
 ib_api_status_t\r
@@ -105,4 +111,22 @@ void
 __srp_cleanup_session(\r
        IN  cl_obj_t    *p_obj );\r
 \r
+ib_api_status_t\r
+srp_session_connect( \r
+  IN           srp_hba_t                       *p_hba,\r
+  IN OUT       p_srp_session_t         *pp_srp_session,\r
+  IN           UCHAR                           svc_idx );\r
+\r
+void\r
+srp_session_adjust_params( \r
+       IN              srp_session_t           *p_session );\r
+\r
+void\r
+srp_session_failed(\r
+IN             srp_session_t*  p_srp_session );\r
+\r
+void\r
+srp_session_recovery_thread(\r
+IN             void*    const          context );\r
+\r
 #endif  /* _SRP_SESSION_H_ */\r