[ofw][SRP] recovery thread updated

Alex Estrin alex.estrin at qlogic.com
Tue Apr 1 20:58:41 PDT 2008


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
+ 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,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_ */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: srp_recovery_thread_updated.diff
Type: application/octet-stream
Size: 44787 bytes
Desc: srp_recovery_thread_updated.diff
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20080401/962234c4/attachment.obj>


More information about the ofw mailing list