[ofw] [SRP] recovery thread

Alex Estrin alex.estrin at qlogic.com
Mon Feb 25 06:47:32 PST 2008


Hello,

Proposed patch is an implementation of failed session recovery thread
(one thread per session).
Some connection functions were reworked to get more discrete control
over session's state.
Most of data path error states now handled.
Also some other necessary minor changes were included:
	- fixed debug mode statistics to handle more than one session
per IOC.
	- connection request response timeout hardcoded numbers replaced
with calculated path roundtrip time values.
	- added limitation for pending queue growth.
	- couple minor typos.

Please review.

Thanks,
Alex.

Index: srp_session.c
===================================================================
--- srp_session.c	(revision 945)
+++ 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
+ at param 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,237 @@
 
(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;
+	}
+	
+	p_srp_session->connection.state = SRP_CONNECT_FAILURE;
+	
+	cl_obj_unlock( &p_srp_session->obj );
+
+	SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_SESSION,
+		("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_SESSION,
+			("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_SESSION,
+		("Pausing Adapter Session %d for %s.\n", target_id,
+		p_hba->ioc_info.profile.id_string ) );
+
+	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_SESSION,
+				("Failed session idx %d connect\n",
target_id ) );
+			continue;
+		}
+
+		p_hba->session_list[target_id] = p_new;
+		p_hba->session_paused[target_id] = FALSE;
+
+		SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_SESSION,
+				("Session idx %d connected. Resuming\n",
target_id ) );
+
+		StorPortDeviceReady( p_hba->p_ext,
+						SP_UNTAGGED,
+						target_id,
+						SP_UNTAGGED );
+
+		return;
+	}
+
+	/* what do we do now ? */
+	SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_SESSION,
+			("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, TRUE );
+
+	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_data_path.c
===================================================================
--- srp_data_path.c	(revision 945)
+++ 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_CONNECTED )
+	{
+		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,16 @@
 					{
 						/* probably a problem
with the Vfx FC san like wire pull*/
 						/* initiate session
recovery */
+						session_recover = TRUE;
+
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") );
-						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 );
+						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 +729,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 +741,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 +802,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 +827,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 +848,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 +871,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 +902,10 @@
 	UNUSED_PARAM( h_cq );
 
 	__srp_process_session_recv_completions( p_srp_session );
-
+	if( p_srp_session->connection.state != SRP_CONNECTED )
+	{
+		srp_session_failed( p_srp_session );
+	}
 	SRP_EXIT( SRP_DBG_DATA );
 }
 
@@ -887,7 +919,7 @@
 @return - none
 */
 static inline
-void
+BOOLEAN
 __srp_build_cmd(
 	IN      PVOID               p_dev_ext,
 	IN OUT  PSCSI_REQUEST_BLOCK p_srb,
@@ -1124,6 +1156,7 @@
 	//set_srp_command_from_host_to_network( p_srp_cmd );
 
 	SRP_EXIT( SRP_DBG_DATA );
+	return TRUE;
 }
 
 /* srp_format_io_request */
@@ -1159,7 +1192,8 @@
 
 	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 )
 	{
 		srp_conn_info_t srp_conn_info;
 
@@ -1180,7 +1214,12 @@
 
 		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
 	{
@@ -1214,8 +1253,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 +1273,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 +1306,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 +1327,10 @@
 	StorPortNotification( RequestComplete, p_dev_ext, p_srb );
 
 exit:
+	if( status != IB_SUCCESS )
+	{
+		srp_session_failed( p_srp_session );
+	}
 	SRP_EXIT( SRP_DBG_DATA );
 }
 
@@ -1483,7 +1546,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 +1570,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_session.h
===================================================================
--- srp_session.h	(revision 945)
+++ 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_ */
Index: srp_hba.c
===================================================================
--- srp_hba.c	(revision 945)
+++ 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,14 @@
 	{
 		if ( p_hba->session_list[i] != NULL )
 		{
-			break;
+			p_session = p_hba->session_list[i];
+			p_hba->session_list[i] = NULL;
+			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 +971,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 +1004,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 +1027,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_hba.h
===================================================================
--- srp_hba.h	(revision 945)
+++ 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_driver.c
===================================================================
--- srp_driver.c	(revision 945)
+++ 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
 
@@ -536,9 +536,10 @@
 		gp_self_do = p_dev_obj;
 	}
 	status = gpfn_pnp( p_dev_obj, p_irp );
-	SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,
-		("gpfn_pnp status = 0x%x.\n", status) );
 
+	SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,
+		("Minor PNP Func %#x gpfn_pnp status = 0x%x.\n", minor,
status) );
+
 	if( minor == IRP_MN_START_DEVICE )
 	{
 		LONG    release_status;
@@ -548,7 +549,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 +558,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 +716,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 +824,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 +867,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_connection.c
===================================================================
--- srp_connection.c	(revision 945)
+++ 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,26 +290,9 @@
 	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;
 	cl_obj_unlock( &p_srp_session->obj );
@@ -316,92 +305,19 @@
 	{
 		SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
 			("Cannot respond to target disconnect request.
Status = %d\n", status) );
+		return;
 	}
 
-	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 +359,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 +655,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 +820,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_connection.h
===================================================================
--- srp_connection.h	(revision 945)
+++ 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;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: srp_recovery_thread.diff
Type: application/octet-stream
Size: 44004 bytes
Desc: srp_recovery_thread.diff
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20080225/31018541/attachment.obj>


More information about the ofw mailing list