2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\r
7 * Redistribution and use in source and binary forms, with or
\r
8 * without modification, are permitted provided that the following
\r
9 * conditions are met:
\r
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\r
15 * - Redistributions in binary form must reproduce the above
\r
16 * copyright notice, this list of conditions and the following
\r
17 * disclaimer in the documentation and/or other materials
\r
18 * provided with the distribution.
\r
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
33 #include "srp_data_path.h"
\r
34 #include "srp_debug.h"
\r
35 #if defined(EVENT_TRACING)
\r
39 #include "srp_connection.tmh"
\r
41 #include "srp_event.h"
\r
42 #include "srp_hca.h"
\r
43 #include "srp_session.h"
\r
46 #include "srp_login_req.h"
\r
47 #include "srp_login_rsp.h"
\r
48 #include "srp_login_rej.h"
\r
50 #include "srp_connection.h"
\r
52 #include <complib/cl_math.h>
\r
54 /* __srp_create_cqs */
\r
56 Creates the send/recv completion queues to be used by this connection
\r
58 @param p_srp_connection - pointer to the connection structure
\r
59 @param p_hca - pointer to the hca structure used by the connection
\r
60 @param p_session - context passed to callback functions
\r
62 @return - result of cq creation
\r
67 IN OUT srp_connection_t *p_srp_connection,
\r
68 IN srp_hca_t *p_hca,
\r
69 IN p_srp_session_t p_session )
\r
71 ib_api_status_t status;
\r
72 ib_cq_create_t cq_create;
\r
75 SRP_ENTER( SRP_DBG_PNP );
\r
77 p_ifc = &p_hca->p_hba->ifc;
\r
80 cq_create.size = SRP_DEFAULT_SEND_Q_DEPTH;
\r
81 cq_create.pfn_comp_cb = srp_send_completion_cb;
\r
82 cq_create.h_wait_obj = NULL;
\r
84 status = p_ifc->create_cq( p_hca->h_ca,
\r
87 srp_async_event_handler_cb,
\r
88 &p_srp_connection->h_send_cq );
\r
89 if( status != IB_SUCCESS )
\r
91 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
92 ("Cannot Create Send Completion Queue. Status = %d\n", status) );
\r
96 // Create Receive CQ
\r
97 cq_create.size = SRP_DEFAULT_RECV_Q_DEPTH;
\r
98 cq_create.pfn_comp_cb = srp_recv_completion_cb;
\r
99 cq_create.h_wait_obj = NULL;
\r
101 status = p_ifc->create_cq( p_hca->h_ca,
\r
104 srp_async_event_handler_cb,
\r
105 &p_srp_connection->h_recv_cq );
\r
106 if( status != IB_SUCCESS )
\r
108 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
109 ("Cannot Create Receive Completion Queue. Status = %d\n", status) );
\r
113 SRP_EXIT( SRP_DBG_PNP );
\r
118 /* __srp_create_qp */
\r
120 Creates the queue pair to be used by this connection
\r
122 @param p_srp_connection - pointer to the connection structure
\r
123 @param p_hca - pointer to the hca structure used by the connection
\r
124 @param p_session - context passed to callback functions
\r
126 @return - result of qp creation
\r
131 IN OUT srp_connection_t *p_srp_connection,
\r
132 IN srp_hca_t *p_hca,
\r
133 IN p_srp_session_t p_session )
\r
135 ib_api_status_t status;
\r
136 ib_qp_create_t qp_create;
\r
137 ib_al_ifc_t *p_ifc;
\r
139 SRP_ENTER( SRP_DBG_PNP );
\r
141 p_ifc = &p_hca->p_hba->ifc;
\r
144 qp_create.qp_type = IB_QPT_RELIABLE_CONN;
\r
145 qp_create.sq_depth = SRP_DEFAULT_SEND_Q_DEPTH;
\r
146 qp_create.rq_depth = SRP_DEFAULT_RECV_Q_DEPTH;
\r
147 qp_create.sq_sge = 1;
\r
148 qp_create.rq_sge = 1;
\r
149 qp_create.h_sq_cq = p_srp_connection->h_send_cq;
\r
150 qp_create.h_rq_cq = p_srp_connection->h_recv_cq;
\r
151 qp_create.sq_signaled = FALSE;//TRUE;
\r
153 status = p_ifc->create_qp( p_hca->h_pd,
\r
156 srp_async_event_handler_cb,
\r
157 &p_srp_connection->h_qp );
\r
158 if ( status != IB_SUCCESS )
\r
160 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
161 ("Cannot Create Queue Pair. Status = %d\n", status) );
\r
164 SRP_EXIT( SRP_DBG_PNP );
\r
171 __srp_create_wc_free_list(
\r
172 IN OUT srp_connection_t *p_connection,
\r
173 IN uint32_t completion_count )
\r
175 cl_status_t status = CL_SUCCESS;
\r
179 SRP_ENTER( SRP_DBG_PNP );
\r
181 p_connection->p_wc_array = cl_zalloc( sizeof( ib_wc_t ) * completion_count );
\r
182 if ( p_connection->p_wc_array == NULL )
\r
184 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
185 ("Failed to allocate %d work completions.\n", completion_count) );
\r
186 status = CL_INSUFFICIENT_MEMORY;
\r
190 p_wc = p_connection->p_wc_array;
\r
192 for ( i = 1; i < completion_count; i++, p_wc++ )
\r
194 p_wc->p_next = (p_wc + 1);
\r
197 p_connection->p_wc_free_list = p_connection->p_wc_array;
\r
200 SRP_EXIT( SRP_DBG_PNP );
\r
206 /* __srp_cm_request_cb */
\r
208 Callback for a connect request - not used by SRP - We initiate connections
\r
210 @param p_cm_request - pointer to the connect request structure
\r
216 __srp_cm_request_cb(
\r
217 IN ib_cm_req_rec_t *p_cm_request)
\r
219 SRP_ENTER( SRP_DBG_PNP );
\r
221 UNUSED_PARAM ( p_cm_request );
\r
223 SRP_EXIT( SRP_DBG_PNP );
\r
226 /* __srp_cm_apr_cb */
\r
228 Callback for alternate path response - not used by SRP
\r
230 @param p_cm_apr_rec - pointer to the alternate path response structure
\r
237 IN ib_cm_apr_rec_t *p_cm_apr_rec )
\r
239 SRP_ENTER( SRP_DBG_PNP );
\r
241 UNUSED_PARAM( p_cm_apr_rec );
\r
243 SRP_EXIT( SRP_DBG_PNP );
\r
246 /* __srp_cm_mra_cb */
\r
248 Callback for message received acknowledgement - ignored by SRP - wait for connect reply
\r
250 @param p_cm_mra_rec - pointer to the message received acknowledgement structure
\r
257 IN ib_cm_mra_rec_t *p_cm_mra_rec)
\r
259 SRP_ENTER( SRP_DBG_PNP );
\r
261 UNUSED_PARAM ( p_cm_mra_rec );
\r
263 SRP_EXIT( SRP_DBG_PNP );
\r
266 /* __srp_cm_dreq_cb */
\r
268 Callback for disconnect request from the target
\r
269 Initiates the disconnect for the session
\r
273 @param p_cm_dreq_rec - pointer to the disconnect request structure
\r
280 IN ib_cm_dreq_rec_t *p_cm_dreq_rec )
\r
282 srp_session_t *p_srp_session = (srp_session_t* __ptr64)p_cm_dreq_rec->qp_context;
\r
283 srp_hba_t *p_hba = p_srp_session->p_hba;
\r
284 ib_cm_drep_t cm_drep;
\r
285 ib_api_status_t status;
\r
287 int retry_count = 0;
\r
289 SRP_ENTER( SRP_DBG_PNP );
\r
291 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,
\r
292 ("Target has issued a disconnect request.\n") );
\r
294 if ( p_hba->adapter_paused == FALSE )
\r
296 p_hba->adapter_paused = TRUE;
\r
297 StorPortBusy( p_hba->p_ext, (ULONG)-1 );
\r
298 StorPortCompleteRequest( p_hba->p_ext,
\r
303 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG, ("Pausing Adapter for %s.\n", p_hba->ioc_info.profile.id_string) );
\r
306 cl_obj_lock( &p_srp_session->obj );
\r
307 p_srp_session->connection.state = SRP_TARGET_DISCONNECTING;
\r
308 cl_obj_unlock( &p_srp_session->obj );
\r
310 cm_drep.p_drep_pdata = NULL;
\r
311 cm_drep.drep_length = 0;
\r
313 status = p_hba->ifc.cm_drep( p_cm_dreq_rec->h_cm_dreq, &cm_drep );
\r
314 if ( status != IB_SUCCESS )
\r
316 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
317 ("Cannot respond to target disconnect request. Status = %d\n", status) );
\r
320 cl_obj_lock( &p_hba->obj );
\r
322 for ( i = 0; i < SRP_MAX_SERVICE_ENTRIES; i++ )
\r
324 if ( p_srp_session == p_hba->session_list[i] )
\r
326 p_hba->session_list[i] = NULL;
\r
331 cl_obj_unlock( &p_hba->obj );
\r
333 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,
\r
334 ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );
\r
335 cl_obj_destroy( &p_srp_session->obj );
\r
341 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,
\r
342 ("Attempting to reconnect %s. Connection Attempt Count = %d.\n",
\r
343 p_hba->ioc_info.profile.id_string,
\r
346 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,
\r
347 ("Creating New Session For Service Entry Index %d.\n",
\r
348 p_hba->ioc_info.profile.num_svc_entries));
\r
349 p_srp_session = srp_new_session( p_hba,
\r
350 p_hba->ioc_info.profile.ioc_guid,
\r
351 &p_hba->p_svc_entries[i],
\r
353 if ( p_srp_session == NULL )
\r
355 status = IB_INSUFFICIENT_MEMORY;
\r
359 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,
\r
360 ("New Session For Service Entry Index %d Created.\n",
\r
361 p_hba->ioc_info.profile.num_svc_entries));
\r
362 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,
\r
363 ("Logging Into Session.\n"));
\r
364 status = srp_session_login( p_srp_session );
\r
365 if ( status == IB_SUCCESS )
\r
367 if ( p_hba->max_sg > p_srp_session->connection.max_scatter_gather_entries )
\r
369 p_hba->max_sg = p_srp_session->connection.max_scatter_gather_entries;
\r
372 if ( p_hba->max_srb_ext_sz > p_srp_session->connection.init_to_targ_iu_sz )
\r
374 p_hba->max_srb_ext_sz =
\r
375 sizeof( srp_send_descriptor_t ) -
\r
377 p_srp_session->connection.init_to_targ_iu_sz;
\r
380 cl_obj_lock( &p_hba->obj );
\r
381 p_hba->session_list[i] = p_srp_session;
\r
382 cl_obj_unlock( &p_hba->obj );
\r
384 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,
\r
385 ("Session Login Issued Successfully.\n"));
\r
389 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
390 ("Session Login Failure Status = %d.\n", status));
\r
391 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,
\r
392 ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );
\r
393 cl_obj_destroy( &p_srp_session->obj );
\r
395 } while ( (status != IB_SUCCESS) && (retry_count < 3) );
\r
397 if ( status == IB_SUCCESS )
\r
399 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,
\r
400 ("Resuming Adapter for %s.\n", p_hba->ioc_info.profile.id_string) );
\r
401 p_hba->adapter_paused = FALSE;
\r
402 StorPortReady( p_hba->p_ext );
\r
403 // StorPortNotification( BusChangeDetected, p_hba->p_ext, 0 );
\r
406 SRP_EXIT( SRP_DBG_PNP );
\r
409 /* __srp_cm_reply_cb */
\r
411 Callback for connect reply from the target
\r
412 The target has accepted our connect/login request
\r
414 @param p_cm_reply - pointer to the connect reply structure
\r
421 IN ib_cm_rep_rec_t *p_cm_reply)
\r
423 srp_session_t *p_srp_session = (srp_session_t* __ptr64)p_cm_reply->qp_context;
\r
424 srp_connection_t *p_connection;
\r
425 srp_login_rsp_t *p_srp_login_rsp = (srp_login_rsp_t* __ptr64)p_cm_reply->p_rep_pdata;
\r
426 ib_api_status_t status;
\r
429 ib_cm_mra_t cm_mra;
\r
430 ib_cm_rtu_t cm_rtu;
\r
431 ib_cm_rej_t cm_rej;
\r
434 cl_status_t cl_status;
\r
435 ib_al_ifc_t *p_ifc;
\r
437 SRP_ENTER( SRP_DBG_PNP );
\r
439 p_ifc = &p_srp_session->p_hba->ifc;
\r
440 p_connection = &p_srp_session->connection;
\r
442 set_srp_login_response_from_network_to_host( p_srp_login_rsp );
\r
443 p_connection->descriptor_format = get_srp_login_response_supported_data_buffer_formats( p_srp_login_rsp );
\r
445 p_connection->request_limit =
\r
446 MIN( get_srp_login_response_request_limit_delta( p_srp_login_rsp ), SRP_DEFAULT_RECV_Q_DEPTH );
\r
447 p_connection->send_queue_depth = p_connection->request_limit;
\r
448 p_connection->recv_queue_depth = p_connection->request_limit;
\r
449 p_connection->init_to_targ_iu_sz = get_srp_login_response_max_init_to_targ_iu( p_srp_login_rsp );
\r
450 p_connection->targ_to_init_iu_sz = get_srp_login_response_max_targ_to_init_iu( p_srp_login_rsp );
\r
452 p_connection->signaled_send_completion_count = p_connection->send_queue_depth / 2;
\r
454 if (( p_connection->descriptor_format & DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS ) == DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS )
\r
456 p_connection->max_scatter_gather_entries =
\r
457 ( MIN( SRP_MAX_IU_SIZE, p_connection->init_to_targ_iu_sz ) - offsetof( srp_cmd_t, additional_cdb )- sizeof(srp_memory_table_descriptor_t)) / sizeof( srp_memory_descriptor_t );
\r
459 else if (( p_connection->descriptor_format & DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR ) == DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR )
\r
461 p_connection->max_scatter_gather_entries =
\r
462 (p_connection->init_to_targ_iu_sz - offsetof( srp_cmd_t, additional_cdb ))/ sizeof( srp_memory_descriptor_t );
\r
464 else /* not reported any descriptor format */
\r
466 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,
\r
467 ("Target does not support valid descriptor formats\n") );
\r
470 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,
\r
471 ("Request Limit = %d, SendQ Depth = %d, RecvQDepth = %d, "
\r
472 "ItoT size = %d, TtoI size = %d, Max S/G = %d\n",
\r
473 p_connection->request_limit,
\r
474 p_connection->send_queue_depth,
\r
475 p_connection->recv_queue_depth,
\r
476 p_connection->init_to_targ_iu_sz,
\r
477 p_connection->targ_to_init_iu_sz,
\r
478 p_connection->max_scatter_gather_entries) );
\r
480 u.cm_mra.svc_timeout = 0x08;
\r
481 u.cm_mra.p_mra_pdata = NULL;
\r
482 u.cm_mra.mra_length = 0;
\r
484 status = p_ifc->cm_mra( p_cm_reply->h_cm_rep, &u.cm_mra );
\r
485 if ( status != IB_SUCCESS )
\r
487 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
488 ("Cannot Send MRA. Status = %d\n", status) );
\r
492 status = p_ifc->modify_cq( p_connection->h_send_cq, &p_connection->send_queue_depth );
\r
493 if ( status != IB_SUCCESS )
\r
495 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,
\r
496 ("Cannot Modify Send Completion Queue Depth. Status = %d\n", status) );
\r
499 status = p_ifc->modify_cq( p_connection->h_recv_cq, &p_connection->recv_queue_depth );
\r
500 if ( status != IB_SUCCESS )
\r
502 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,
\r
503 ("Cannot Modify Recv Completion Queue Depth. Status = %d\n", status) );
\r
506 cl_status = __srp_create_wc_free_list( p_connection, (p_connection->request_limit * 2) );/* Send/Recv */
\r
507 if ( cl_status != CL_SUCCESS )
\r
512 status = srp_init_descriptors( &p_srp_session->descriptors,
\r
513 p_connection->request_limit,
\r
514 p_connection->targ_to_init_iu_sz,
\r
515 &p_srp_session->p_hba->ifc,
\r
516 p_srp_session->hca.h_pd,
\r
517 p_connection->h_qp );
\r
518 if ( status != IB_SUCCESS )
\r
520 cl_free( p_connection->p_wc_array );
\r
521 p_connection->p_wc_array = NULL;
\r
522 p_connection->p_wc_free_list = NULL;
\r
524 p_connection->state = SRP_CONNECT_FAILURE;
\r
525 cl_memclr( &u.cm_rej, sizeof(u.cm_rej) );
\r
526 u.cm_rej.rej_status = IB_REJ_INSUF_RESOURCES;
\r
527 p_ifc->cm_rej( p_cm_reply->h_cm_rep, &u.cm_rej );
\r
531 u.cm_rtu.access_ctrl = IB_AC_LOCAL_WRITE | IB_AC_RDMA_READ | IB_AC_RDMA_WRITE;
\r
533 /* Have to set to 0 to indicate not to modify because Tavor doesn't support this */
\r
534 u.cm_rtu.sq_depth = 0 /*p_connection->request_limit*/;
\r
535 u.cm_rtu.rq_depth = 0 /*p_connection->request_limit*/;
\r
537 u.cm_rtu.p_rtu_pdata = NULL;
\r
538 u.cm_rtu.rtu_length = 0;
\r
539 u.cm_rtu.pfn_cm_apr_cb = __srp_cm_apr_cb;
\r
540 u.cm_rtu.pfn_cm_dreq_cb = __srp_cm_dreq_cb;
\r
542 status = p_ifc->cm_rtu( p_cm_reply->h_cm_rep, &u.cm_rtu );
\r
543 if ( status != IB_SUCCESS )
\r
545 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
546 ("Cannot Send RTU. Status = %d\n", status) );
\r
547 p_connection->state = SRP_CONNECT_FAILURE;
\r
551 p_connection->state = SRP_CONNECTED;
\r
553 status = p_ifc->rearm_cq( p_connection->h_send_cq, FALSE );
\r
554 if ( status != IB_SUCCESS)
\r
556 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
557 ("ib_rearm_cq() for send cq failed!, status 0x%x", status) );
\r
559 // TODO: Kill session and inform port driver link down storportnotification
\r
563 status = p_ifc->rearm_cq( p_connection->h_recv_cq, FALSE );
\r
564 if ( status != IB_SUCCESS)
\r
566 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
567 ("ib_rearm_cq() for recv failed!, status 0x%x", status) );
\r
569 // TODO: Kill session and inform port driver link down storportnotification
\r
575 cl_status = cl_event_signal( &p_connection->conn_req_event );
\r
577 SRP_EXIT( SRP_DBG_PNP );
\r
581 /* __srp_cm_rej_cb */
\r
583 Callback for connect reject from the target
\r
584 The target has rejected our connect/login request
\r
586 @param p_cm_reject - pointer to the connect reject structure
\r
593 IN ib_cm_rej_rec_t *p_cm_reject)
\r
595 srp_session_t *p_srp_session = (srp_session_t* __ptr64)p_cm_reject->qp_context;
\r
596 srp_connection_t *p_connection;
\r
597 srp_login_rej_t *p_srp_login_rej = (srp_login_rej_t* __ptr64)p_cm_reject->p_rej_pdata;
\r
598 cl_status_t cl_status;
\r
600 SRP_ENTER( SRP_DBG_PNP );
\r
602 p_connection = &p_srp_session->connection;
\r
604 if( p_srp_login_rej )
\r
606 set_srp_login_reject_from_network_to_host( p_srp_login_rej ); // <-- Is this coming back NULL?
\r
607 p_connection->reject_reason = get_srp_login_reject_reason( p_srp_login_rej );
\r
609 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
610 ("Login Rejected. IBT Code = 0x%x, SRP Code = 0x%x\n",
\r
611 p_cm_reject->rej_status, p_connection->reject_reason ) );
\r
612 switch( p_connection->reject_reason )
\r
614 case LIREJ_INIT_TO_TARG_IU_LENGTH_TOO_LARGE:
\r
615 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
616 ("REQUESTED IU_SIZE %d\n",
\r
617 p_connection->req_max_iu_msg_size ));
\r
619 case LIREJ_UNSUPPORTED_DATA_BUFFER_DESCRIPTOR_FORMAT:
\r
620 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
621 ("REQUESTED DESC FORMAT: %#x, SUPPORTED FORMAT %#x\n",
\r
622 p_connection->descriptor_format,
\r
623 get_srp_login_reject_supported_data_buffer_formats(p_srp_login_rej) ));
\r
624 __srp_issue_session_login( p_connection, (srp_hca_t *)&p_srp_session->hca, p_connection->ioc_max_send_msg_depth );
\r
632 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
633 ("Login Rejected. IBT Code = 0x%x\n",
\r
634 p_cm_reject->rej_status) );
\r
636 p_connection->state = SRP_CONNECT_FAILURE;
\r
638 cl_status = cl_event_signal( &p_connection->conn_req_event );
\r
640 SRP_EXIT( SRP_DBG_PNP );
\r
643 /* __srp_issue_session_login */
\r
645 Initializes and issues a login/cm connect request to the target
\r
647 @param p_connection - pointer to the connection structure
\r
648 @param p_hca - pointer to the hca structure used by this connection
\r
649 @param send_msg_depth - initial request limit delta value
\r
651 @return - result of login/cm connect request operations
\r
653 #pragma optimize( "", off )
\r
656 __srp_issue_session_login(
\r
657 IN OUT srp_connection_t *p_connection,
\r
658 IN srp_hca_t *p_hca,
\r
659 IN uint8_t send_msg_depth )
\r
661 ib_api_status_t status;
\r
662 ib_cm_req_t cm_req;
\r
663 srp_login_req_t login_req;
\r
665 SRP_ENTER( SRP_DBG_PNP );
\r
667 cl_memclr( &cm_req, sizeof(ib_cm_req_t) );
\r
669 cm_req.svc_id = p_connection->service_id;
\r
671 cm_req.flags = 0; // event used instead of IB_FLAGS_SYNC
\r
672 cm_req.max_cm_retries = 8;
\r
673 cm_req.p_primary_path = p_connection->p_path_rec;
\r
675 /*already tried to login before and failed ? */
\r
676 if ( !p_connection->reject_reason )
\r
678 p_connection->descriptor_format = DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR | DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS;
\r
680 else if ( p_connection->reject_reason == LIREJ_UNSUPPORTED_DATA_BUFFER_DESCRIPTOR_FORMAT )
\r
682 p_connection->descriptor_format = DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR;
\r
686 p_connection->state = SRP_CONNECT_FAILURE;
\r
690 p_connection->req_max_iu_msg_size = ( p_connection->ioc_max_send_msg_size >= SRP_MAX_IU_SIZE )? SRP_MAX_IU_SIZE: p_connection->ioc_max_send_msg_size;
\r
692 Build SRP Login request
\r
694 setup_srp_login_request( &login_req,
\r
696 p_connection->req_max_iu_msg_size,
\r
697 p_connection->descriptor_format,
\r
698 MCA_TERMINATE_EXISTING,
\r
699 &p_connection->init_port_id,
\r
700 &p_connection->targ_port_id );
\r
701 set_srp_login_request_from_host_to_network(&login_req);
\r
703 cm_req.p_req_pdata = (const uint8_t *)&login_req;
\r
704 cm_req.req_length = (uint8_t)get_srp_login_request_length( &login_req );
\r
706 cm_req.qp_type = IB_QPT_RELIABLE_CONN;
\r
707 cm_req.h_qp = p_connection->h_qp;
\r
709 /* The maximum number of outstanding RDMA read/atomic operations. */
\r
710 status = srp_get_responder_resources( p_hca, &cm_req.resp_res );
\r
711 if ( status != IB_SUCCESS )
\r
716 cm_req.init_depth = send_msg_depth;
\r
718 cm_req.remote_resp_timeout = 15;
\r
719 cm_req.flow_ctrl = FALSE;
\r
720 cm_req.local_resp_timeout = 16;
\r
721 cm_req.retry_cnt = 1;
\r
722 cm_req.rnr_nak_timeout = 0; /* 655.36 ms */
\r
723 cm_req.rnr_retry_cnt = 6;
\r
725 cm_req.pfn_cm_rep_cb = __srp_cm_reply_cb;
\r
726 cm_req.pfn_cm_req_cb = NULL; /* Set only for P2P */
\r
727 cm_req.pfn_cm_mra_cb = __srp_cm_mra_cb;
\r
728 cm_req.pfn_cm_rej_cb = __srp_cm_rej_cb;
\r
730 cm_req.pkey = p_connection->p_path_rec->pkey;
\r
732 status = p_hca->p_hba->ifc.cm_req( &cm_req );
\r
733 if ( status == IB_SUCCESS )
\r
735 p_connection->state = SRP_CONNECT_REQUESTED;
\r
739 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
740 ("Cannot Send Connect Request. Status = %d\n", status) );
\r
741 p_connection->state = SRP_CONNECT_FAILURE;
\r
745 SRP_EXIT( SRP_DBG_PNP );
\r
749 #pragma optimize( "", on )
\r
751 /* srp_init_connection */
\r
753 Initializes a connection structure
\r
755 @param p_connection - pointer to the connection structure
\r
756 @param p_path_rec - pointer to the path to the target
\r
757 @param p_targ_port_id - pointer to the target port id to which we want to connect
\r
758 @param service_id - service id to which we want to connect
\r
760 @return - always success (for now)
\r
763 srp_init_connection(
\r
764 IN OUT srp_connection_t *p_connection,
\r
765 IN ib_path_rec_t *p_path_rec,
\r
766 IN srp_ib_targ_port_id_t *p_targ_port_id,
\r
767 IN ib_net64_t service_id )
\r
769 SRP_ENTER( SRP_DBG_PNP );
\r
771 cl_memclr( p_connection, sizeof(*p_connection) );\
\r
773 p_connection->initialized = TRUE;
\r
775 p_connection->state = SRP_NOT_CONNECTED;
\r
777 p_connection->p_path_rec = p_path_rec;
\r
778 p_connection->targ_port_id = *p_targ_port_id;
\r
779 p_connection->service_id = service_id;
\r
780 p_connection->send_queue_depth = SRP_DEFAULT_SEND_Q_DEPTH;
\r
781 p_connection->recv_queue_depth = SRP_DEFAULT_RECV_Q_DEPTH;
\r
783 SRP_EXIT( SRP_DBG_PNP );
\r
785 return ( IB_SUCCESS );
\r
790 Orchestrates the processing required to connect to a target device
\r
792 @param p_connection - pointer to the connection structure
\r
793 @param p_hca - pointer to the hca structure used by this connection
\r
794 @param initiator_extension - value used for id_extension of the initiator port id
\r
795 @param send_msg_depth - initial request limit delta value
\r
796 @param p_session - context passed to callback functions
\r
798 @return - result of connect operations
\r
802 IN OUT srp_connection_t *p_connection,
\r
803 IN srp_hca_t *p_hca,
\r
804 IN uint64_t initiator_extension,
\r
805 IN uint8_t send_msg_depth,
\r
806 IN p_srp_session_t p_session )
\r
808 ib_api_status_t status;
\r
809 cl_status_t cl_status;
\r
811 SRP_ENTER( SRP_DBG_PNP );
\r
813 p_connection->init_port_id.guid = p_hca->ca_guid;
\r
814 p_connection->init_port_id.id_extension = initiator_extension;
\r
815 p_connection->ioc_max_send_msg_size = cl_ntoh32 (p_session->p_hba->ioc_info.profile.send_msg_size);
\r
816 p_connection->ioc_max_send_msg_depth = send_msg_depth;
\r
817 p_connection->reject_reason = 0;
\r
819 status = __srp_create_cqs( p_connection, p_hca, p_session );
\r
820 if ( status != IB_SUCCESS )
\r
825 status = __srp_create_qp( p_connection, p_hca, p_session );
\r
826 if ( status != IB_SUCCESS )
\r
831 cl_status = cl_event_init( &p_connection->conn_req_event, TRUE );
\r
832 if ( cl_status != CL_SUCCESS )
\r
834 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
835 ("Cannot Initialize Connect Request Event. Status = %d\n", cl_status) );
\r
836 status = cl_status;
\r
840 status = __srp_issue_session_login( p_connection, p_hca, send_msg_depth );
\r
841 if ( status != IB_SUCCESS )
\r
843 cl_event_destroy( &p_connection->conn_req_event );
\r
847 cl_status = cl_event_wait_on( &p_connection->conn_req_event, EVENT_NO_TIMEOUT, FALSE );
\r
848 if ( cl_status != CL_SUCCESS )
\r
850 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,
\r
851 ("Wait On Connect Request Event Failed. Status = %d\n", cl_status) );
\r
852 status = cl_status;
\r
853 cl_event_destroy( &p_connection->conn_req_event );
\r
857 cl_event_destroy( &p_connection->conn_req_event );
\r
859 if ( p_connection->state != SRP_CONNECTED )
\r
866 SRP_EXIT( SRP_DBG_PNP );
\r
871 /* srp_free_connection */
\r
873 Frees connection resources
\r
875 @param p_connection - pointer to the connection structure
\r
880 srp_free_connection(
\r
881 IN srp_connection_t *p_srp_connection )
\r
883 SRP_ENTER( SRP_DBG_PNP );
\r
885 if ( p_srp_connection->initialized == TRUE )
\r
887 if ( p_srp_connection->p_wc_array != NULL )
\r
889 cl_free( p_srp_connection->p_wc_array );
\r
892 cl_event_destroy( &p_srp_connection->conn_req_event );
\r
894 cl_memclr( p_srp_connection, sizeof( *p_srp_connection ) );
\r
897 SRP_EXIT( SRP_DBG_PNP );
\r