\r
#include <complib/cl_math.h>\r
\r
+#if DBG\r
+\r
+extern void* gp_session[SRP_MAX_SERVICE_ENTRIES];\r
+\r
+#endif\r
+\r
/* __srp_create_cqs */\r
/*!\r
Creates the send/recv completion queues to be used by this connection\r
srp_hba_t *p_hba = p_srp_session->p_hba;\r
ib_cm_drep_t cm_drep;\r
ib_api_status_t status;\r
- int i;\r
- int retry_count = 0;\r
\r
SRP_ENTER( SRP_DBG_PNP );\r
\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
- ("Target has issued a disconnect request.\n") );\r
-\r
- if ( p_hba->adapter_paused == FALSE )\r
- {\r
- p_hba->adapter_paused = TRUE;\r
- StorPortBusy( p_hba->p_ext, (ULONG)-1 );\r
- StorPortCompleteRequest( p_hba->p_ext,\r
- SP_UNTAGGED,\r
- SP_UNTAGGED,\r
- SP_UNTAGGED,\r
- SRB_STATUS_BUSY );\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG, ("Pausing Adapter for %s.\n", p_hba->ioc_info.profile.id_string) );\r
- }\r
-\r
cl_obj_lock( &p_srp_session->obj );\r
- p_srp_session->connection.state = SRP_TARGET_DISCONNECTING;\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
cl_obj_unlock( &p_srp_session->obj );\r
\r
cm_drep.p_drep_pdata = NULL;\r
("Cannot respond to target disconnect request. Status = %d\n", status) );\r
}\r
\r
- cl_obj_lock( &p_hba->obj );\r
-\r
- for ( i = 0; i < SRP_MAX_SERVICE_ENTRIES; i++ )\r
- {\r
- if ( p_srp_session == p_hba->session_list[i] )\r
- {\r
- p_hba->session_list[i] = NULL;\r
- break;\r
- }\r
- }\r
-\r
- cl_obj_unlock( &p_hba->obj );\r
-\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
- ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );\r
- cl_obj_destroy( &p_srp_session->obj );\r
-\r
- do\r
- {\r
- retry_count++;\r
-\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
- ("Attempting to reconnect %s. Connection Attempt Count = %d.\n",\r
- p_hba->ioc_info.profile.id_string,\r
- retry_count) );\r
-\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
- ("Creating New Session For Service Entry Index %d.\n",\r
- p_hba->ioc_info.profile.num_svc_entries));\r
- p_srp_session = srp_new_session(\r
- p_hba, &p_hba->p_svc_entries[i], &status );\r
- if ( p_srp_session == NULL )\r
- {\r
- status = IB_INSUFFICIENT_MEMORY;\r
- break;\r
- }\r
-\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
- ("New Session For Service Entry Index %d Created.\n",\r
- p_hba->ioc_info.profile.num_svc_entries));\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
- ("Logging Into Session.\n"));\r
- status = srp_session_login( p_srp_session );\r
- if ( status == IB_SUCCESS )\r
- {\r
- if ( p_hba->max_sg > p_srp_session->connection.max_scatter_gather_entries )\r
- {\r
- p_hba->max_sg = p_srp_session->connection.max_scatter_gather_entries;\r
- }\r
-\r
- if ( p_hba->max_srb_ext_sz > p_srp_session->connection.init_to_targ_iu_sz )\r
- {\r
- p_hba->max_srb_ext_sz =\r
- sizeof( srp_send_descriptor_t ) -\r
- SRP_MAX_IU_SIZE +\r
- p_srp_session->connection.init_to_targ_iu_sz;\r
- }\r
-\r
- cl_obj_lock( &p_hba->obj );\r
- p_hba->session_list[i] = p_srp_session;\r
- cl_obj_unlock( &p_hba->obj );\r
-\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
- ("Session Login Issued Successfully.\n"));\r
- }\r
- else\r
- {\r
- SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
- ("Session Login Failure Status = %d.\n", status));\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
- ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );\r
- cl_obj_destroy( &p_srp_session->obj );\r
- }\r
- } while ( (status != IB_SUCCESS) && (retry_count < 3) );\r
+ SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,\r
+ ("Target has issued a disconnect request for Session %d ref_cnt = %d.\n",\r
+ p_srp_session->target_id,\r
+ p_srp_session->obj.ref_cnt) );\r
\r
- if ( status == IB_SUCCESS )\r
+ if( !p_hba->adapter_stopped )\r
{\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
- ("Resuming Adapter for %s.\n", p_hba->ioc_info.profile.id_string) );\r
- p_hba->adapter_paused = FALSE;\r
- StorPortReady( p_hba->p_ext );\r
-// StorPortNotification( BusChangeDetected, p_hba->p_ext, 0 );\r
+ srp_session_failed( p_srp_session );\r
}\r
\r
SRP_EXIT( SRP_DBG_PNP );\r
\r
p_connection->request_limit =\r
MIN( get_srp_login_response_request_limit_delta( p_srp_login_rsp ), SRP_DEFAULT_RECV_Q_DEPTH );\r
+ \r
+ if( ib_ioc_profile_get_vend_id( &p_srp_session->p_hba->ioc_info.profile) == 0x00066a &&\r
+ cl_ntoh32( p_srp_session->p_hba->ioc_info.profile.subsys_id ) == 0x38 )\r
+ {\r
+ /* workaround for FVIC */\r
+ p_connection->request_limit /= 2;\r
+ }\r
\r
+ p_connection->max_limit = p_connection->request_limit;\r
p_connection->request_threashold = 2;\r
#if DBG\r
p_srp_session->x_req_limit = p_connection->request_limit;\r
#endif\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
- ( "request_limit_delta %d, SRP_DEFAULT_RECV_Q_DEPTH %d, request_threashold %d\n", \r
- get_srp_login_response_request_limit_delta( p_srp_login_rsp ), \r
- SRP_DEFAULT_RECV_Q_DEPTH, p_connection->request_threashold ));\r
\r
p_connection->send_queue_depth = p_connection->request_limit;\r
p_connection->recv_queue_depth = p_connection->request_limit;\r
p_connection->init_to_targ_iu_sz = get_srp_login_response_max_init_to_targ_iu( p_srp_login_rsp );\r
p_connection->targ_to_init_iu_sz = get_srp_login_response_max_targ_to_init_iu( p_srp_login_rsp );\r
\r
- p_connection->signaled_send_completion_count = p_connection->send_queue_depth / 2;\r
+ p_connection->signaled_send_completion_count = 32;\r
\r
if (( p_connection->descriptor_format & DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS ) == DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS )\r
{\r
\r
cm_req.init_depth = send_msg_depth;\r
\r
- cm_req.remote_resp_timeout = 15;\r
+ cm_req.remote_resp_timeout = ib_path_rec_pkt_life( p_connection->p_path_rec ) + 1;\r
cm_req.flow_ctrl = FALSE;\r
- cm_req.local_resp_timeout = 16;\r
+ cm_req.local_resp_timeout = ib_path_rec_pkt_life( p_connection->p_path_rec ) + 1;\r
cm_req.retry_cnt = 1;\r
cm_req.rnr_nak_timeout = 0; /* 655.36 ms */\r
cm_req.rnr_retry_cnt = 6;\r
status = IB_ERROR;\r
goto exit;\r
}\r
+ \r
+ cl_thread_init( &p_session->recovery_thread, \r
+ (cl_pfn_thread_callback_t)srp_session_recovery_thread,\r
+ (void *)p_session, "srp_thread" );\r
+#if DBG\r
+ gp_session[p_session->target_id] = p_session;\r
+#endif\r
\r
exit:\r
SRP_EXIT( SRP_DBG_PNP );\r
\r
\r
\r
+\r
\r
atomic32_t tag;\r
atomic32_t request_limit;\r
+ atomic32_t max_limit;\r
int32_t request_threashold;\r
uint32_t init_to_targ_iu_sz;\r
uint32_t targ_to_init_iu_sz;\r
ib_api_status_t status;\r
ib_wc_t *p_wc_done_list = NULL;\r
ib_wc_t *p_wc;\r
+ BOOLEAN to_recover = FALSE;\r
\r
SRP_ENTER( SRP_DBG_DATA );\r
\r
SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("ib_poll_cq() failed!, status 0x%x\n", status) );\r
\r
- // TODO: Kill session and inform port driver link down scsiportnotification\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
cl_obj_unlock( &p_srp_session->obj );\r
return;\r
}\r
case IB_WCS_SUCCESS:\r
break;\r
case IB_WCS_WR_FLUSHED_ERR:\r
- // TODO: Kill session and inform port driver link down scsiportnotification\r
+ if( !to_recover )\r
+ to_recover = TRUE;\r
SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
("Send Completion Status %s Vendore Status = 0x%x, \n",\r
p_srp_session->p_hba->ifc.get_wc_status_str( p_wc->status ),\r
get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
break;\r
default:\r
- // TODO: Kill session and inform port driver link down scsiportnotification\r
+ to_recover = TRUE;\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("Send Completion Status %s Vendore Status = 0x%x, \n",\r
p_srp_session->p_hba->ifc.get_wc_status_str( p_wc->status ),\r
p_wc = p_wc_done_list;\r
}\r
\r
+ if( !to_recover )\r
+ {\r
/* Re-arm the CQ for more completions */\r
status = p_srp_session->p_hba->ifc.rearm_cq(\r
p_srp_session->connection.h_send_cq, FALSE );\r
{\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("ib_rearm_cq() failed!, status 0x%x\n", status) );\r
-\r
- // TODO: Kill session and inform port driver link down scsiportnotification\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+ to_recover = TRUE;\r
+ }\r
+ }\r
+ if( to_recover == TRUE )\r
+ {\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
}\r
\r
cl_obj_deref( &p_srp_session->obj );\r
\r
__srp_process_session_send_completions( p_srp_session );\r
\r
+ if( p_srp_session->connection.state == SRP_CONNECT_FAILURE )\r
+ {\r
+ if( !p_srp_session->p_hba->adapter_stopped )\r
+ {\r
+ srp_session_failed( p_srp_session );\r
+ }\r
+ }\r
+\r
SRP_EXIT( SRP_DBG_DATA );\r
}\r
\r
return status;\r
}\r
\r
-void\r
+ib_api_status_t\r
__srp_post_io_request(\r
IN PVOID p_dev_ext,\r
IN OUT PSCSI_REQUEST_BLOCK p_srb, \r
\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, "\r
- "Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+ "Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
g_srb_status_name[p_srb->SrbStatus],\r
p_srb->SrbStatus,\r
g_srb_function_name[p_srb->Function],\r
\r
exit:\r
SRP_EXIT( SRP_DBG_DATA );\r
+ return status;\r
}\r
\r
static \r
-void\r
+ib_api_status_t\r
__srp_repost_io_request(\r
IN srp_session_t *p_srp_session )\r
{\r
srp_hba_t *p_hba;\r
srp_send_descriptor_t *p_send_descriptor = NULL;\r
srp_descriptors_t *p_descriptors = &p_srp_session->descriptors;\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
\r
SRP_ENTER( SRP_DBG_DATA );\r
\r
/* post the request */\r
p_hba = p_srp_session->p_hba;\r
p_send_descriptor = PARENT_STRUCT(p_list_item, srp_send_descriptor_t,list_item);\r
- __srp_post_io_request( p_hba->p_ext, p_send_descriptor->p_srb, p_srp_session );\r
+ ib_status = __srp_post_io_request( p_hba->p_ext, p_send_descriptor->p_srb, p_srp_session );\r
}\r
\r
cl_atomic_dec( &p_srp_session->repost_is_on );\r
\r
exit:\r
SRP_EXIT( SRP_DBG_DATA );\r
+ return ib_status;\r
}\r
\r
static inline void\r
srp_rsp_t *p_srp_rsp;\r
uint8_t response_status;\r
srp_send_descriptor_t *p_send_descriptor;\r
+ uint64_t response_tag;\r
+ BOOLEAN session_recover = FALSE;\r
\r
SRP_ENTER( SRP_DBG_DATA );\r
\r
set_srp_response_from_network_to_host( p_srp_rsp );\r
\r
response_status = get_srp_response_status( p_srp_rsp );\r
+ response_tag = get_srp_response_tag( (srp_rsp_t *)p_recv_descriptor->p_data_segment );\r
\r
p_send_descriptor = srp_find_matching_send_descriptor(\r
- &p_srp_session->descriptors,\r
- get_srp_response_tag( (srp_rsp_t *)p_recv_descriptor->p_data_segment ) );\r
+ &p_srp_session->descriptors, response_tag );\r
if ( p_send_descriptor == NULL )\r
{\r
/* Repost the recv descriptor */\r
{\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("Failed to post send descriptor. Status = %d.\n", status) );\r
- // TODO: Kill session and inform port driver link down scsiportnotification\r
}\r
-\r
+ else\r
+ {\r
__srp_fix_request_limit( p_srp_session, p_srp_rsp );\r
- __srp_repost_io_request( p_srp_session );\r
-\r
+ }\r
SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
- ("Matching Send Descriptor Not Found.\n") );\r
+ ("Matching Send Descriptor not Found: tag %#I64x\n", response_tag ) );\r
\r
- goto exit;\r
+ if( status == IB_SUCCESS &&\r
+ !cl_qlist_count( &p_srp_session->descriptors.sent_descriptors ) )\r
+ {\r
+ /* Seem all commands from sent queue were aborted by timeout already */\r
+ /* most likely Target get stuck. schedule session recovery */\r
+ status = IB_ERROR;\r
+ }\r
+ return ( status );\r
}\r
\r
SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
("Recv Completion Received for Function = %s(0x%x), "\r
- "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+ "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
g_srb_function_name[p_send_descriptor->p_srb->Function],\r
p_send_descriptor->p_srb->Function,\r
p_send_descriptor->p_srb->PathId,\r
\r
set_srp_tsk_mgmt_from_network_to_host( p_srp_tsk_mgmt );\r
\r
-\r
if(response_status == SCSISTAT_GOOD)\r
{\r
p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_SUCCESS;\r
p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;\r
SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
("Scsi Error %s (%#x) Received for Function = %s(0x%x), "\r
- "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+ "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
g_srb_scsi_status_name[response_status],\r
response_status,\r
g_srb_function_name[p_send_descriptor->p_srb->Function],\r
p_srp_session->connection.h_qp, &p_recv_descriptor->wr, NULL );\r
if ( status != IB_SUCCESS )\r
{\r
+ session_recover = TRUE;\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("Failed to post recv descriptor. Status = %d.\n", status) );\r
- // TODO: Kill session and inform port driver link down storportnotification\r
}\r
\r
- __srp_fix_request_limit( p_srp_session, p_srp_rsp );\r
- __srp_repost_io_request( p_srp_session );\r
-\r
- __srp_dump_srb_info( p_send_descriptor);\r
-\r
- status = __srp_clean_send_descriptor( p_send_descriptor, p_srp_session );\r
- if ( status != IB_SUCCESS )\r
- {\r
- SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
- ("Failed to unmap FMR Status = %d.\n", status) );\r
- // TODO: Kill session and inform port driver link down storportnotification\r
}\r
\r
- StorPortNotification( RequestComplete, p_srp_session->p_hba->p_ext, p_send_descriptor->p_srb );\r
- }\r
-\r
-\r
- \r
break;\r
}\r
\r
p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;\r
SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
("Scsi Error %s (%#x) Received for Function = %s(0x%x), "\r
- "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+ "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
g_srb_scsi_status_name[response_status],\r
response_status,\r
g_srb_function_name[p_send_descriptor->p_srb->Function],\r
p_send_descriptor->p_srb->SenseInfoBufferLength ) );\r
SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
("Sense Data SENSE_KEY 0x%02x ADDITIONAL_SENSE_CODE"\r
- "0x%02x ADDITIONAL_SENSE_QUILIFIER 0x%02x.\n",\r
+ "0x%02x ADDITIONAL_SENSE_QUALIFIER 0x%02x.\n",\r
p_sense_data[2],p_sense_data[12],p_sense_data[13]) );\r
\r
if ( ((p_sense_data[2]&0xf) == 0x0b /*ABORTED_COMMAND*/) &&\r
{\r
/* probably a problem with the Vfx FC san like wire pull*/\r
/* initiate session recovery */\r
+ session_recover = TRUE;\r
+ if( p_srp_session->p_hba->session_paused[p_srp_session->target_id] == FALSE )\r
+ {\r
+ p_srp_session->p_hba->session_paused[p_srp_session->target_id] = TRUE;\r
SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
("Sense Data indicates FC link connectivity has been lost.\n") );\r
- StorPortPauseDevice( p_srp_session->p_hba->p_ext,\r
- p_send_descriptor->p_srb->PathId,\r
- p_send_descriptor->p_srb->TargetId,\r
- p_send_descriptor->p_srb->Lun,\r
- 5 );\r
+ StorPortDeviceBusy( p_srp_session->p_hba->p_ext,\r
+ SP_UNTAGGED,\r
+ p_srp_session->target_id,\r
+ SP_UNTAGGED,\r
+ (ULONG)-1 );\r
}\r
- \r
+ }\r
}\r
\r
if ( get_srp_response_di_over( p_srp_rsp ) || get_srp_response_do_over( p_srp_rsp ) )\r
p_srp_session->connection.h_qp, &p_recv_descriptor->wr, NULL );\r
if ( status != IB_SUCCESS )\r
{\r
+ session_recover = TRUE;\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("Failed to post recv descriptor. Status = %d.\n", status) );\r
- // TODO: Kill session and inform port driver link down storportnotification\r
}\r
\r
- __srp_fix_request_limit( p_srp_session, p_srp_rsp );\r
- __srp_repost_io_request( p_srp_session );\r
-\r
- __srp_dump_srb_info( p_send_descriptor);\r
-\r
- status = __srp_clean_send_descriptor( p_send_descriptor, p_srp_session );\r
- if ( status != IB_SUCCESS )\r
- {\r
- SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
- ("Failed to unmap FMR Status = %d.\n", status) );\r
- // TODO: Kill session and inform port driver link down storportnotification\r
- }\r
- \r
- StorPortNotification( RequestComplete, p_srp_session->p_hba->p_ext, p_send_descriptor->p_srb );\r
break;\r
\r
case SRP_LOGIN_REQ:\r
case SRP_CRED_RSP:\r
case SRP_AER_RSP:\r
default:\r
- CL_ASSERT ( 0 );\r
+ SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
+ ("Illegal SRP IU CMD/RSP %#x received\n", \r
+ get_srp_iu_buffer_type( (srp_iu_buffer_t *)p_send_descriptor->data_segment ) ) );\r
+ session_recover = TRUE;\r
break;\r
}\r
\r
-exit:\r
+ status = __srp_clean_send_descriptor( p_send_descriptor, p_srp_session );\r
+ if ( status != IB_SUCCESS )\r
+ {\r
+ session_recover = TRUE;\r
+ }\r
+\r
+ if( session_recover == TRUE )\r
+ {\r
+ status = IB_ERROR;\r
+ }\r
+ else \r
+ {\r
+ __srp_fix_request_limit( p_srp_session, p_srp_rsp );\r
+ status = __srp_repost_io_request( p_srp_session );\r
+ }\r
+\r
+ __srp_dump_srb_info( p_send_descriptor);\r
+\r
+ StorPortNotification( RequestComplete, p_srp_session->p_hba->p_ext, p_send_descriptor->p_srb );\r
+\r
SRP_EXIT( SRP_DBG_DATA );\r
\r
return ( status );\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("ib_poll_cq() failed!, status 0x%x\n", status) );\r
\r
- // TODO: Kill session and inform port driver link down scsiportnotification\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+\r
SRP_EXIT( SRP_DBG_DATA );\r
cl_obj_unlock( &p_srp_session->obj );\r
return;\r
status = __srp_process_recv_completion( p_recv_descriptor, p_srp_session );\r
if ( status != IB_SUCCESS )\r
{\r
- // TODO: Kill session and inform port driver link down scsiportnotification\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+ cl_obj_deref( &p_srp_session->obj );\r
+ return;\r
}\r
}\r
else\r
p_srp_session->p_hba->ifc.get_wc_status_str( p_wc->status )));\r
\r
}\r
+\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+ cl_obj_deref( &p_srp_session->obj );\r
+ return;\r
}\r
\r
/* Put onto head of free list */\r
{\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("ib_rearm_cq() failed!, status 0x%x\n", status) );\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
\r
- // TODO: Kill session and inform port driver link down scsiportnotification\r
+ cl_obj_deref( &p_srp_session->obj );\r
+ return;\r
}\r
\r
cl_obj_deref( &p_srp_session->obj );\r
UNUSED_PARAM( h_cq );\r
\r
__srp_process_session_recv_completions( p_srp_session );\r
-\r
+ if( p_srp_session->connection.state == SRP_CONNECT_FAILURE )\r
+ {\r
+ srp_session_failed( p_srp_session );\r
+ }\r
SRP_EXIT( SRP_DBG_DATA );\r
}\r
\r
@return - none\r
*/\r
static inline\r
-void\r
+BOOLEAN\r
__srp_build_cmd(\r
IN PVOID p_dev_ext,\r
IN OUT PSCSI_REQUEST_BLOCK p_srb,\r
//set_srp_command_from_host_to_network( p_srp_cmd );\r
\r
SRP_EXIT( SRP_DBG_DATA );\r
+ return TRUE;\r
}\r
\r
/* srp_format_io_request */\r
\r
p_srp_session = p_hba->session_list[p_srb->TargetId];\r
\r
- if ( p_srp_session != NULL )\r
+ if ( p_srp_session != NULL && \r
+ p_srp_session->connection.state == SRP_CONNECTED &&\r
+ !p_hba->session_paused[p_srb->TargetId] )\r
{\r
srp_conn_info_t srp_conn_info;\r
\r
\r
srp_build_send_descriptor( p_dev_ext, p_srb, &srp_conn_info );\r
\r
- __srp_build_cmd( p_dev_ext, p_srb, &srp_conn_info );\r
+ result = __srp_build_cmd( p_dev_ext, p_srb, &srp_conn_info );\r
+ \r
+ if( result != TRUE )\r
+ SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
+ ("BUILD command %#x failed = %#x tag %#I64x\n",\r
+ p_srb->Cdb[0], p_srb->SrbStatus, srp_conn_info.tag ) );\r
}\r
else\r
{\r
// Handle the error case here\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("Cannot Find Session For Target ID = %d\n", p_srb->TargetId) );\r
- cl_obj_unlock( &p_hba->obj );\r
+\r
p_srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;\r
+ cl_obj_unlock( &p_hba->obj );\r
result = FALSE;\r
}\r
\r
-\r
SRP_EXIT( SRP_DBG_DATA );\r
return ( result );\r
}\r
\r
p_srp_session = p_hba->session_list[p_srb->TargetId];\r
\r
- if ( p_srp_session != NULL )\r
+ if( p_hba->session_paused[p_srb->TargetId] == TRUE )\r
+ {\r
+ cl_obj_unlock( &p_hba->obj );\r
+ p_srb->SrbStatus = SRB_STATUS_BUSY;\r
+ goto err;\r
+ }\r
+\r
+ if ( p_srp_session != NULL && \r
+ p_srp_session->connection.state == SRP_CONNECTED )\r
{\r
cl_obj_ref( &p_srp_session->obj );\r
cl_obj_unlock( &p_hba->obj );\r
!cl_is_qlist_empty( &p_descriptors->pending_descriptors ) ||\r
p_srp_session->repost_is_on )\r
{\r
+ int32_t num_pending_desc = (int32_t)cl_qlist_count( &p_descriptors->pending_descriptors );\r
cl_spinlock_release ( &p_descriptors->pending_list_lock );\r
srp_add_pending_descriptor( p_descriptors, p_send_descriptor );\r
+ \r
+ /* don't allow pending queue grow indefinitely */\r
+ if( num_pending_desc >= p_srp_session->connection.max_limit )\r
+ { \r
+ StorPortDeviceBusy( p_dev_ext, \r
+ p_srb->PathId,\r
+ p_srb->TargetId,\r
+ p_srb->Lun,\r
+ 1 );\r
+ }\r
+\r
cl_obj_deref( &p_srp_session->obj );\r
goto exit;\r
}\r
cl_spinlock_release ( &p_descriptors->pending_list_lock );\r
\r
- __srp_post_io_request( p_dev_ext, p_srb, p_srp_session );\r
+ status = __srp_post_io_request( p_dev_ext, p_srb, p_srp_session );\r
cl_obj_deref( &p_srp_session->obj );\r
goto exit;\r
}\r
err:\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, "\r
- "Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
+ "Target = 0x%x, Lun = 0x%x, tag 0x%I64x\n",\r
g_srb_status_name[p_srb->SrbStatus],\r
p_srb->SrbStatus,\r
g_srb_function_name[p_srb->Function],\r
StorPortNotification( RequestComplete, p_dev_ext, p_srb );\r
\r
exit:\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ p_srp_session->connection.state = SRP_CONNECT_FAILURE;\r
+ srp_session_failed( p_srp_session );\r
+ }\r
SRP_EXIT( SRP_DBG_DATA );\r
}\r
\r
{\r
srp_session_t *p_srp_session = p_session;\r
\r
- if (p_srp_session == NULL)\r
+ if (p_srp_session == NULL ||\r
+ p_srp_session->connection.state != SRP_CONNECTED )\r
return;\r
\r
p_srp_session->x_pkt_fmr = 0;\r
{\r
srp_session_t *p_srp_session = p_session;\r
\r
- if (p_srp_session == NULL)\r
+ if (p_srp_session == NULL || \r
+ p_srp_session->connection.state != SRP_CONNECTED )\r
return;\r
\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_DATA,\r
srp_x_clean(\r
IN void *p_session );\r
\r
-void *gp_session = NULL;\r
+void* gp_session[SRP_MAX_SERVICE_ENTRIES];\r
\r
#endif\r
\r
("KeReleaseMutex status = %d.\n", release_status) );\r
}\r
\r
- #if DBG\r
+ #if DBG_STATISTICS\r
/* statistics */\r
\r
/* this function is called sometimes in the begging of the test with \r
/* sometimes it's called once in 50msec, so we'll print once in 20 times */\r
static int interval = 40; /* 2 sec */\r
static int cnt = 0;\r
+ static int i;\r
if (++cnt >= interval)\r
{\r
cnt = 0;\r
- srp_x_print( gp_session );\r
- srp_x_clean( gp_session );\r
+ if(i > 3 ) i = 0;\r
+ srp_x_print( gp_session[i] );\r
+ srp_x_clean( gp_session[i] );\r
+ i++;\r
}\r
}\r
\r
\r
if ( (p_srb->Lun == 0) && (p_srp_session != NULL) )\r
{\r
- p_hba->session_list[p_srb->TargetId] = NULL;\r
-\r
- CL_ASSERT( p_srp_session != NULL );\r
-\r
p_srp_session->p_shutdown_srb = p_srb;\r
- cl_obj_destroy( &p_srp_session->obj );\r
\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
- ("Returning SrbStatus %s(0x%x) for "\r
- "Function = %s(0x%x), Path = 0x%x, "\r
- "Target = 0x%x, Lun = 0x%x\n",\r
- g_srb_status_name[p_srb->SrbStatus],\r
- p_srb->SrbStatus,\r
- g_srb_function_name[p_srb->Function],\r
- p_srb->Function,\r
- p_srb->PathId,\r
- p_srb->TargetId,\r
- p_srb->Lun) );\r
+ if( !p_hba->adapter_stopped )\r
+ {\r
+ p_hba->adapter_stopped = TRUE;\r
+ srp_disconnect_sessions( p_hba );\r
+ }\r
}\r
else\r
{\r
SRP_ENTER( SRP_DBG_PNP );\r
\r
UNUSED_PARAM( p_dev_ext );\r
- UNUSED_PARAM( path_id );\r
\r
+ StorPortCompleteRequest( p_dev_ext, (UCHAR)path_id, SP_UNTAGGED, SP_UNTAGGED, SRB_STATUS_NO_HBA );\r
+ \r
SRP_EXIT( SRP_DBG_PNP );\r
return FALSE;\r
}\r
{\r
SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
("HBA Object ref_cnt = %d\n", p_ext->p_hba->obj.ref_cnt) );\r
+ if( !p_ext->p_hba->adapter_stopped )\r
+ p_ext->p_hba->adapter_stopped = TRUE;\r
+ srp_disconnect_sessions( p_ext->p_hba );\r
cl_obj_destroy( &p_ext->p_hba->obj );\r
p_ext->p_hba = NULL;\r
}\r
{\r
int retry_count = 0;\r
\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
- ("Creating New Session For Service Entry Index %d.\n",\r
- p_hba->ioc_info.profile.num_svc_entries));\r
-\r
- p_session = srp_new_session(\r
- p_hba, &p_hba->p_svc_entries[i], &status );\r
- if( p_session == NULL )\r
- {\r
- status = IB_INSUFFICIENT_MEMORY;\r
- continue;\r
- }\r
+ do{\r
+ retry_count++;\r
\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
- ("New Session For Service Entry Index %d Created.\n",\r
- p_hba->ioc_info.profile.num_svc_entries));\r
+ SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
+ ("Creating New Session For Service Entry Index %d.\n", i ));\r
+\r
+ p_session = srp_new_session(\r
+ p_hba, \r
+ &p_hba->p_svc_entries[i],\r
+ &p_hba->p_srp_path_record->path_rec,\r
+ &status );\r
+ if( p_session == NULL )\r
+ {\r
+ status = IB_INSUFFICIENT_MEMORY;\r
+ break;\r
+ }\r
\r
- do\r
- {\r
- retry_count++;\r
+ SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
+ ("New Session For Service Entry Index %d Created.\n", i ));\r
\r
SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
- ("Attempting to connect %s. Connection Attempt Count = %d.\n",\r
- p_hba->ioc_info.profile.id_string,\r
+ ("Attempting to connect %s. Svc Idx %d; Connection Attempt Count = %d.\n", \r
+ p_hba->ioc_info.profile.id_string, i,\r
retry_count) );\r
SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
("Logging Into Session.\n"));\r
{\r
any_ioc_connected = TRUE;\r
\r
- if ( (p_hba->max_sg >\r
- p_session->connection.max_scatter_gather_entries)\r
- && !(p_session->connection.descriptor_format &\r
- DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS) )\r
- {\r
- p_hba->max_sg = p_session->connection.max_scatter_gather_entries;\r
- }\r
-\r
- if ( p_hba->max_srb_ext_sz > p_session->connection.init_to_targ_iu_sz )\r
- {\r
- p_hba->max_srb_ext_sz =\r
- sizeof( srp_send_descriptor_t ) -\r
- SRP_MAX_IU_SIZE +\r
- p_session->connection.init_to_targ_iu_sz;\r
- }\r
+ srp_session_adjust_params( p_session );\r
\r
cl_obj_lock( &p_hba->obj );\r
+ p_session->target_id = (UCHAR)i;\r
p_hba->session_list[i] = p_session;\r
cl_obj_unlock( &p_hba->obj );\r
\r
else\r
{\r
SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_PNP,\r
- ("Session Login Failure Status = %d.\n", status));\r
+ ("Session Login for Service Idx %d Failure Status = %d.\n", i, status));\r
+ cl_obj_destroy( &p_session->obj );\r
}\r
+\r
} while ( (status != IB_SUCCESS) && (retry_count < 3) );\r
\r
- if( status != IB_SUCCESS )\r
- {\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
- ("Session Object ref_cnt = %d\n", p_session->obj.ref_cnt) );\r
- cl_obj_destroy( &p_session->obj );\r
- }\r
}\r
\r
if ( any_ioc_connected == TRUE )\r
{\r
status = IB_SUCCESS;\r
- if ( p_hba->adapter_paused == TRUE )\r
+ for( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
{\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
- ("Resuming Adapter for %s.\n",\r
- p_hba->ioc_info.profile.id_string) );\r
- p_hba->adapter_paused = FALSE;\r
- StorPortReady( p_hba->p_ext );\r
- //StorPortNotification( BusChangeDetected, p_hba->p_ext, 0 );\r
+ p_session = p_hba->session_list[i];\r
+ \r
+ if( p_session != NULL &&\r
+ p_session->connection.state == SRP_CONNECTED && \r
+ p_hba->session_paused[i] == TRUE )\r
+ {\r
+ SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
+ ("Resuming Adapter Session %d for %s.\n", i,\r
+ p_hba->ioc_info.profile.id_string) );\r
+\r
+ p_hba->session_paused[i] = FALSE;\r
+ StorPortDeviceReady( p_hba->p_ext, SP_UNTAGGED, (UCHAR)i, SP_UNTAGGED );\r
+ }\r
}\r
}\r
\r
return status;\r
}\r
\r
-static void\r
-__srp_disconnect_sessions(\r
- IN srp_hba_t *p_hba,\r
- IN BOOLEAN pause_adapter )\r
+void\r
+srp_disconnect_sessions(\r
+ IN srp_hba_t *p_hba )\r
{\r
uint32_t i;\r
srp_session_t *p_session;\r
{\r
if ( p_hba->session_list[i] != NULL )\r
{\r
- break;\r
+ p_session = p_hba->session_list[i];\r
+ p_hba->session_list[i] = NULL;\r
+ p_session->connection.state = SRP_CONNECT_FAILURE;\r
+ srp_session_failed( p_session );\r
}\r
}\r
\r
cl_obj_unlock( &p_hba->obj );\r
\r
- if ( i == p_hba->ioc_info.profile.num_svc_entries )\r
- {\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
- ("No current connections to %s.\n",\r
- p_hba->ioc_info.profile.id_string) );\r
- goto exit;\r
- }\r
-\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
- ("Current path to %s has been lost.\n",\r
- p_hba->ioc_info.profile.id_string) );\r
-\r
- p_hba->p_srp_path_record = NULL;\r
-\r
- if ( pause_adapter == TRUE )\r
- {\r
- if ( p_hba->adapter_paused == FALSE )\r
- {\r
- p_hba->adapter_paused = TRUE;\r
- StorPortBusy( p_hba->p_ext, (ULONG)-1 );\r
- StorPortCompleteRequest( p_hba->p_ext,\r
- SP_UNTAGGED,\r
- SP_UNTAGGED,\r
- SP_UNTAGGED,\r
- SRB_STATUS_BUSY );\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
- ("Pausing Adapter for %s.\n",\r
- p_hba->ioc_info.profile.id_string) );\r
- }\r
- }\r
-\r
- /* Destroy all the connections. */\r
- SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
- ("Destroy all connections to %s.\n",\r
- p_hba->ioc_info.profile.id_string) );\r
-\r
- for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
- {\r
- cl_obj_lock( &p_hba->obj );\r
- p_session = p_hba->session_list[i];\r
- p_hba->session_list[i] = NULL;\r
- cl_obj_unlock( &p_hba->obj );\r
-\r
- if ( p_session != NULL )\r
- {\r
- SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
- ("Session Object ref_cnt = %d\n", p_session->obj.ref_cnt) );\r
- __srp_cleanup_session ( &p_session->obj );\r
- cl_obj_destroy( &p_session->obj );\r
- }\r
- else\r
- {\r
- SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,\r
- ("Session for Target ID %d on %s is NULL.\n",\r
- i,\r
- p_hba->ioc_info.profile.id_string) ); // <-- OK in a shutdown or target disconnect\r
- }\r
- }\r
-\r
-exit:\r
SRP_EXIT( SRP_DBG_PNP );\r
}\r
\r
\r
SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
("Hey!!! Our IOC went away.\n") );\r
-\r
- __srp_disconnect_sessions( p_hba, FALSE );\r
+ \r
+ if( !p_hba->adapter_stopped )\r
+ p_hba->adapter_stopped = TRUE;\r
+ \r
+ srp_disconnect_sessions( p_hba );\r
__srp_remove_path_records( p_hba );\r
+\r
SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
- ("HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
+ ("IB_PNP_IOC_REMOVE HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt ) );\r
+\r
break;\r
\r
case IB_PNP_IOC_PATH_ADD:\r
p_hba->ioc_info.profile.id_string) );\r
status = __srp_connect_path( p_hba );\r
}\r
+\r
+ SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
+ (" IOC_PATH ADD HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt ) );\r
break;\r
\r
case IB_PNP_IOC_PATH_REMOVE:\r
\r
if ( g_srp_system_shutdown == FALSE )\r
{\r
- __srp_disconnect_sessions( p_hba, TRUE );\r
- status = __srp_connect_path( p_hba );\r
- }\r
- else\r
- {\r
- __srp_disconnect_sessions( p_hba, FALSE );\r
+ srp_disconnect_sessions( p_hba );\r
}\r
}\r
\r
srp_path_record_t *p_srp_path_record;\r
cl_qlist_t path_record_list;\r
cl_spinlock_t path_record_list_lock;\r
- BOOLEAN adapter_paused;\r
+ BOOLEAN adapter_stopped;\r
\r
uint32_t max_sg;\r
uint32_t max_srb_ext_sz;\r
-\r
/* List of sessions indexed by target id */\r
p_srp_session_t session_list[SRP_MAX_SERVICE_ENTRIES];\r
+ BOOLEAN session_paused[SRP_MAX_SERVICE_ENTRIES];\r
} srp_hba_t;\r
\r
\r
IN cl_obj_t* const p_drv_obj,\r
OUT struct _srp_ext* const p_ext );\r
\r
+void\r
+srp_disconnect_sessions(\r
+ IN srp_hba_t *p_hba );\r
+\r
#endif /* _SRP_HBA_H_ */\r
#include "srp_session.h"\r
#include <stdlib.h>\r
\r
-#if DBG\r
-extern void *gp_session;\r
-#endif\r
-\r
/* __srp_destroying_session */\r
/*!\r
Called when session has been marked for destruction\r
@param p_hba - pointer to the hba associated with the new session\r
@param ioc_guid - pointer to the target's ioc guid\r
@param p_svc_entry - pointer to the service entry\r
+@param p_path_rec - pointer to path record to use.\r
+\r
@param p_status - pointer to the reason code\r
\r
@return - Pointer to new session or NULL if failure. See p_status for reason code.\r
srp_new_session(\r
IN srp_hba_t *p_hba,\r
IN ib_svc_entry_t *p_svc_entry,\r
+ IN ib_path_rec_t *p_path_rec,\r
OUT ib_api_status_t *p_status )\r
{\r
uint64_t target_id_extension;\r
goto exit;\r
}\r
\r
+ if( p_path_rec == NULL )\r
+ {\r
+ goto exit;\r
+ }\r
+\r
p_srp_session = (srp_session_t*)cl_zalloc( sizeof(srp_session_t) );\r
if ( p_srp_session == NULL )\r
{\r
&p_hba->ioc_info.profile,\r
p_hba->info.ca_guid,\r
target_id_extension,\r
- &p_hba->p_srp_path_record->path_rec,\r
- p_svc_entry->id );\r
+ p_path_rec,\r
+ p_svc_entry->id );\r
if ( *p_status != IB_SUCCESS )\r
{\r
cl_free( p_srp_session );\r
SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
("After Insert Rel Session Object ref_cnt = %d\n",\r
p_srp_session->obj.ref_cnt) );\r
-\r
-#if DBG\r
- gp_session = p_srp_session;\r
-#endif\r
-\r
exit:\r
SRP_EXIT( SRP_DBG_SESSION );\r
\r
(uint8_t)p_srp_session->p_hba->ioc_info.profile.send_msg_depth,\r
p_srp_session );\r
\r
- if ( status != IB_SUCCESS )\r
- { // clean resources, taken upon login\r
- srp_close_ca( &p_srp_session->hca );\r
- srp_destroy_descriptors( &p_srp_session->descriptors );\r
- }\r
-\r
exit:\r
SRP_EXIT( SRP_DBG_SESSION );\r
return ( status );\r
}\r
+\r
+void\r
+srp_session_failed(\r
+IN srp_session_t* p_srp_session )\r
+{\r
+\r
+ SRP_ENTER( SRP_DBG_SESSION );\r
+ \r
+ if( !p_srp_session )\r
+ return;\r
+\r
+ cl_obj_lock( &p_srp_session->obj );\r
+ \r
+ if( p_srp_session->obj.state != CL_INITIALIZED )\r
+ {\r
+ cl_obj_unlock( &p_srp_session->obj );\r
+ return;\r
+ }\r
+ \r
+ if( p_srp_session->connection.state != SRP_CONNECT_FAILURE )\r
+ {\r
+ cl_obj_unlock( &p_srp_session->obj );\r
+ return;\r
+ }\r
+ p_srp_session->connection.state = SRP_CONNECTION_CLOSING;\r
+ \r
+ cl_obj_unlock( &p_srp_session->obj );\r
+\r
+ SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+ ("Session Idx %d failed\n", p_srp_session->target_id ) );\r
+\r
+ cl_event_signal( &p_srp_session->offload_event );\r
+}\r
+\r
+ib_api_status_t\r
+srp_session_connect( \r
+ IN srp_hba_t *p_hba,\r
+ IN OUT p_srp_session_t *pp_srp_session,\r
+ IN UCHAR svc_idx )\r
+{\r
+ ib_api_status_t ib_status;\r
+ srp_path_record_t *p_srp_path_rec;\r
+ srp_session_t *p_session;\r
+ uint64_t target_id_extension;\r
+\r
+ SRP_ENTER( SRP_DBG_SESSION );\r
+ \r
+ if( *pp_srp_session != NULL )\r
+ {\r
+ return IB_ERROR;\r
+ }\r
+\r
+ cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
+ if( !cl_qlist_count( &p_hba->path_record_list ) )\r
+ {\r
+ cl_spinlock_release( &p_hba->path_record_list_lock );\r
+ return IB_NOT_FOUND;\r
+ }\r
+\r
+ p_srp_path_rec = (srp_path_record_t *)cl_qlist_head( &p_hba->path_record_list );\r
+ \r
+ cl_spinlock_release( &p_hba->path_record_list_lock );\r
+\r
+ if( p_srp_path_rec == (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
+ {\r
+ return IB_NOT_FOUND;\r
+ }\r
+\r
+ ib_status = __srp_validate_service_entry( &p_hba->p_svc_entries[svc_idx], &target_id_extension );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_SESSION,\r
+ ("Failed validate service entry status %x\n", ib_status ));\r
+ return ib_status;\r
+ }\r
+ \r
+ p_session = srp_new_session( p_hba,\r
+ &p_hba->p_svc_entries[svc_idx],\r
+ &p_srp_path_rec->path_rec,\r
+ &ib_status );\r
+ \r
+ if( ib_status != IB_SUCCESS || p_session == NULL )\r
+ {\r
+ SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_SESSION,\r
+ ("Failed create Session for SVC idx %d status %x\n", svc_idx, ib_status ));\r
+ \r
+ *pp_srp_session = NULL;\r
+ \r
+ return ib_status;\r
+ }\r
+\r
+ ib_status = srp_session_login( p_session );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_SESSION,\r
+ ("Failed Session Login status %x\n", ib_status ));\r
+\r
+ *pp_srp_session = NULL;\r
+ \r
+ cl_obj_destroy( &p_session->obj );\r
+ \r
+ return ib_status;\r
+ }\r
+ srp_session_adjust_params( p_session );\r
+\r
+ cl_obj_lock( &p_hba->obj );\r
+\r
+ p_session->target_id = svc_idx;\r
+\r
+ *pp_srp_session = p_session;\r
+\r
+ cl_obj_unlock( &p_hba->obj );\r
+\r
+\r
+ SRP_EXIT( SRP_DBG_SESSION );\r
+ return ib_status;\r
+}\r
+\r
+void\r
+srp_session_adjust_params( \r
+ IN srp_session_t *p_session )\r
+{\r
+\r
+ if ( ( p_session->p_hba->max_sg > p_session->connection.max_scatter_gather_entries )\r
+ && !( p_session->connection.descriptor_format & DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS) )\r
+ {\r
+ p_session->p_hba->max_sg = p_session->connection.max_scatter_gather_entries;\r
+ }\r
+\r
+ if ( p_session->p_hba->max_srb_ext_sz > p_session->connection.init_to_targ_iu_sz )\r
+ {\r
+ p_session->p_hba->max_srb_ext_sz =\r
+ sizeof( srp_send_descriptor_t ) -\r
+ SRP_MAX_IU_SIZE +\r
+ p_session->connection.init_to_targ_iu_sz;\r
+ }\r
+}\r
+\r
+static void\r
+__srp_session_recovery(\r
+IN srp_session_t* p_failed_session , \r
+IN BOOLEAN reconnect_request )\r
+{\r
+ ib_api_status_t ib_status;\r
+ srp_hba_t* p_hba;\r
+ srp_session_t* p_new;\r
+ srp_session_t* p_old;\r
+ UCHAR target_id;\r
+ int retry_count;\r
+\r
+ SRP_ENTER( SRP_DBG_SESSION );\r
+ \r
+ if( !p_failed_session )\r
+ return;\r
+ if ( ( p_hba = p_failed_session->p_hba ) == NULL )\r
+ return;\r
+\r
+ p_old = p_failed_session;\r
+ target_id = p_old->target_id;\r
+ p_hba->session_list[target_id] = NULL;\r
+\r
+ if( !reconnect_request )\r
+ {\r
+ /* we're done here */\r
+ SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+ ("Session Id: %d won't recover\n", p_old->target_id ) );\r
+ cl_obj_destroy( &p_old->obj );\r
+ return;\r
+ }\r
+\r
+ if( !p_hba->session_paused[target_id] )\r
+ {\r
+ p_hba->session_paused[target_id] = TRUE;\r
+\r
+ StorPortDeviceBusy( p_hba->p_ext,\r
+ SP_UNTAGGED,\r
+ target_id,\r
+ SP_UNTAGGED, \r
+ (ULONG)-1 );\r
+ }\r
+\r
+ SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+ ("Pausing Adapter Session %d\n", target_id ) );\r
+\r
+ cl_obj_destroy( &p_old->obj );\r
+\r
+ for( retry_count=0; retry_count < 3 ; retry_count++ )\r
+ {\r
+ ib_status = srp_session_connect( p_hba, &p_new, target_id );\r
+\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+ ("Failed session idx %d connect\n", target_id ) );\r
+ \r
+ continue;\r
+ }\r
+\r
+ p_hba->session_list[target_id] = p_new;\r
+\r
+ SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+ ("Session idx %d connected. Resuming\n", target_id ) );\r
+\r
+ StorPortDeviceReady( p_hba->p_ext,\r
+ SP_UNTAGGED,\r
+ target_id,\r
+ SP_UNTAGGED );\r
+\r
+ p_hba->session_paused[target_id] = FALSE;\r
+ \r
+ return;\r
+ }\r
+\r
+ /* what do we do now ? */\r
+ SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
+ ("Session idx %d recovery failed\n", target_id) );\r
+\r
+ return;\r
+}\r
+\r
+void\r
+srp_session_recovery_thread(\r
+ IN void* const context )\r
+{\r
+ srp_session_t* p_session = (srp_session_t *)context;\r
+ cl_status_t status;\r
+\r
+ if( p_session == NULL )\r
+ return;\r
+\r
+ cl_event_init( &p_session->offload_event, FALSE);\r
+\r
+ status = cl_event_wait_on( &p_session->offload_event, EVENT_NO_TIMEOUT, FALSE );\r
+\r
+ __srp_session_recovery( p_session, !p_session->p_hba->adapter_stopped );\r
+}\r
\r
SCSI_REQUEST_BLOCK *p_shutdown_srb;\r
\r
+ /* keep session level SCSI address */\r
+ UCHAR target_id;\r
+ cl_event_t offload_event;\r
+ cl_thread_t recovery_thread;\r
+\r
#if DBG\r
/* statistics */\r
\r
srp_new_session(\r
IN srp_hba_t *p_hba,\r
IN ib_svc_entry_t *p_svc_entry,\r
+ IN ib_path_rec_t *p_path_rec,\r
OUT ib_api_status_t *p_status );\r
\r
ib_api_status_t\r
__srp_cleanup_session(\r
IN cl_obj_t *p_obj );\r
\r
+ib_api_status_t\r
+srp_session_connect( \r
+ IN srp_hba_t *p_hba,\r
+ IN OUT p_srp_session_t *pp_srp_session,\r
+ IN UCHAR svc_idx );\r
+\r
+void\r
+srp_session_adjust_params( \r
+ IN srp_session_t *p_session );\r
+\r
+void\r
+srp_session_failed(\r
+IN srp_session_t* p_srp_session );\r
+\r
+void\r
+srp_session_recovery_thread(\r
+IN void* const context );\r
+\r
#endif /* _SRP_SESSION_H_ */\r