Unfortunately, we have no capacity now to test this patch thoroughly
enough.
If you feel confident with this fix, I can commit it to the trunk.
It would be great, if someone from the community could test it in his
environment. 

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

Reply via email to