6e3b75aa5f6b3dbd88d5ed98fb1e6529b87d69bc
[mirror/winof/.git] / ulp / srp / kernel / srp_connection.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\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
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\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
19  *\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
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 #include "srp_data_path.h"\r
34 #include "srp_debug.h"\r
35 #include "srp_event.h"\r
36 #include "srp_hca.h"\r
37 #include "srp_session.h"\r
38 \r
39 #include "srp.h"\r
40 #include "srp_login_req.h"\r
41 #include "srp_login_rsp.h"\r
42 #include "srp_login_rej.h"\r
43 \r
44 #include "srp_connection.h"\r
45 \r
46 #include <complib/cl_math.h>\r
47 \r
48 /* __srp_create_cqs */\r
49 /*!\r
50 Creates the send/recv completion queues to be used by this connection\r
51 \r
52 @param p_srp_connection - pointer to the connection structure\r
53 @param p_hca            - pointer to the hca structure used by the connection\r
54 @param p_session        - context passed to callback functions\r
55 \r
56 @return - result of cq creation\r
57 */\r
58 static\r
59 ib_api_status_t\r
60 __srp_create_cqs(\r
61         IN OUT  srp_connection_t    *p_srp_connection,\r
62         IN      srp_hca_t           *p_hca,\r
63         IN      p_srp_session_t     p_session )\r
64 {\r
65         ib_api_status_t status;\r
66         ib_cq_create_t  cq_create;\r
67         ib_al_ifc_t             *p_ifc;\r
68 \r
69         SRP_ENTER( SRP_DBG_PNP );\r
70 \r
71         p_ifc = &p_hca->p_hba->ifc;\r
72 \r
73         // Create Send CQ\r
74         cq_create.size = SRP_DEFAULT_SEND_Q_DEPTH;\r
75         cq_create.pfn_comp_cb = srp_send_completion_cb;\r
76         cq_create.h_wait_obj = NULL;\r
77 \r
78         status = p_ifc->create_cq( p_hca->h_ca,\r
79                                                    &cq_create,\r
80                                                    p_session,\r
81                                                    srp_async_event_handler_cb,\r
82                                                    &p_srp_connection->h_send_cq );\r
83         if( status != IB_SUCCESS )\r
84         {\r
85                 SRP_TRACE( SRP_DBG_ERROR,\r
86                         ("Cannot Create Send Completion Queue. Status = %d\n", status) );\r
87                 goto exit;\r
88         }\r
89 \r
90         // Create Receive CQ\r
91         cq_create.size = SRP_DEFAULT_RECV_Q_DEPTH;\r
92         cq_create.pfn_comp_cb = srp_recv_completion_cb;\r
93         cq_create.h_wait_obj = NULL;\r
94 \r
95         status = p_ifc->create_cq( p_hca->h_ca,\r
96                                                    &cq_create,\r
97                                                    p_session,\r
98                                                    srp_async_event_handler_cb,\r
99                                                    &p_srp_connection->h_recv_cq );\r
100         if( status != IB_SUCCESS )\r
101         {\r
102                 SRP_TRACE( SRP_DBG_ERROR,\r
103                         ("Cannot Create Receive Completion Queue. Status = %d\n", status) );\r
104         }\r
105 \r
106 exit:\r
107         SRP_EXIT( SRP_DBG_PNP );\r
108 \r
109         return ( status );\r
110 }\r
111 \r
112 /* __srp_create_qp */\r
113 /*!\r
114 Creates the queue pair to be used by this connection\r
115 \r
116 @param p_srp_connection - pointer to the connection structure\r
117 @param p_hca            - pointer to the hca structure used by the connection\r
118 @param p_session        - context passed to callback functions\r
119 \r
120 @return - result of qp creation\r
121 */\r
122 static\r
123 ib_api_status_t\r
124 __srp_create_qp(\r
125         IN OUT  srp_connection_t    *p_srp_connection,\r
126         IN      srp_hca_t           *p_hca,\r
127         IN      p_srp_session_t     p_session )\r
128 {\r
129         ib_api_status_t status;\r
130         ib_qp_create_t  qp_create;\r
131         ib_al_ifc_t             *p_ifc;\r
132 \r
133         SRP_ENTER( SRP_DBG_PNP );\r
134 \r
135         p_ifc = &p_hca->p_hba->ifc;\r
136 \r
137         // Create QP\r
138         qp_create.qp_type = IB_QPT_RELIABLE_CONN;\r
139         qp_create.sq_depth = SRP_DEFAULT_SEND_Q_DEPTH;\r
140         qp_create.rq_depth = SRP_DEFAULT_RECV_Q_DEPTH;\r
141         qp_create.sq_sge = 1;\r
142         qp_create.rq_sge = 1;\r
143         qp_create.h_sq_cq = p_srp_connection->h_send_cq;\r
144         qp_create.h_rq_cq = p_srp_connection->h_recv_cq;\r
145         qp_create.sq_signaled = FALSE;//TRUE;\r
146 \r
147         status = p_ifc->create_qp( p_hca->h_pd,\r
148                                                    &qp_create,\r
149                                                    p_session,\r
150                                                    srp_async_event_handler_cb,\r
151                                                    &p_srp_connection->h_qp );\r
152         if ( status != IB_SUCCESS )\r
153         {\r
154                 SRP_TRACE( SRP_DBG_ERROR,\r
155                         ("Cannot Create Queue Pair. Status = %d\n", status) );\r
156         }\r
157 \r
158         SRP_EXIT( SRP_DBG_PNP );\r
159 \r
160         return ( status );\r
161 }\r
162 \r
163 static\r
164 cl_status_t\r
165 __srp_create_wc_free_list(\r
166         IN OUT  srp_connection_t    *p_connection,\r
167         IN      uint32_t            completion_count )\r
168 {\r
169         cl_status_t status = CL_SUCCESS;\r
170         ib_wc_t     *p_wc;\r
171         uint32_t    i;\r
172 \r
173         SRP_ENTER( SRP_DBG_PNP );\r
174 \r
175         p_connection->p_wc_array = cl_zalloc( sizeof( ib_wc_t ) * completion_count );\r
176         if ( p_connection->p_wc_array == NULL )\r
177         {\r
178                 SRP_TRACE( SRP_DBG_ERROR,\r
179                         ("Failed to allocate %d work completions.\n",  completion_count) );\r
180                 status = CL_INSUFFICIENT_MEMORY;\r
181                 goto exit;\r
182         }\r
183 \r
184         p_wc = p_connection->p_wc_array;\r
185 \r
186         for ( i = 1; i < completion_count; i++, p_wc++ )\r
187         {\r
188                 p_wc->p_next = (p_wc + 1);\r
189         }\r
190 \r
191         p_connection->p_wc_free_list = p_connection->p_wc_array;\r
192 \r
193 exit:\r
194         SRP_EXIT( SRP_DBG_PNP );\r
195 \r
196         return ( status );\r
197 }\r
198 \r
199 \r
200 /* __srp_cm_request_cb */\r
201 /*!\r
202 Callback for a connect request - not used by SRP - We initiate connections\r
203 \r
204 @param p_cm_request - pointer to the connect request structure\r
205 \r
206 @return - none\r
207 */\r
208 static\r
209 void\r
210 __srp_cm_request_cb(\r
211         IN  ib_cm_req_rec_t     *p_cm_request)\r
212 {\r
213         SRP_ENTER( SRP_DBG_PNP );\r
214 \r
215         UNUSED_PARAM ( p_cm_request );\r
216 \r
217         SRP_EXIT( SRP_DBG_PNP );\r
218 }\r
219 \r
220 /* __srp_cm_apr_cb */\r
221 /*!\r
222 Callback for alternate path response - not used by SRP\r
223 \r
224 @param p_cm_apr_rec - pointer to the alternate path response structure\r
225 \r
226 @return - none\r
227 */\r
228 static\r
229 void\r
230 __srp_cm_apr_cb(\r
231         IN  ib_cm_apr_rec_t *p_cm_apr_rec )\r
232 {\r
233         SRP_ENTER( SRP_DBG_PNP );\r
234 \r
235         UNUSED_PARAM( p_cm_apr_rec );\r
236 \r
237         SRP_EXIT( SRP_DBG_PNP );\r
238 }\r
239 \r
240 /* __srp_cm_mra_cb */\r
241 /*!\r
242 Callback for message received acknowledgement - ignored by SRP - wait for connect reply\r
243 \r
244 @param p_cm_mra_rec - pointer to the message received acknowledgement structure\r
245 \r
246 @return - none\r
247 */\r
248 static\r
249 void\r
250 __srp_cm_mra_cb(\r
251         IN  ib_cm_mra_rec_t     *p_cm_mra_rec)\r
252 {\r
253         SRP_ENTER( SRP_DBG_PNP );\r
254 \r
255         UNUSED_PARAM ( p_cm_mra_rec );\r
256 \r
257         SRP_EXIT( SRP_DBG_PNP );\r
258 }\r
259 \r
260 /* __srp_cm_dreq_cb */\r
261 /*!\r
262 Callback for disconnect request from the target\r
263 Initiates the disconnect for the session\r
264 \r
265 TODO:\r
266 \r
267 @param p_cm_dreq_rec - pointer to the disconnect request structure\r
268 \r
269 @return - none\r
270 */\r
271 static\r
272 void\r
273 __srp_cm_dreq_cb(\r
274         IN  ib_cm_dreq_rec_t    *p_cm_dreq_rec )\r
275 {\r
276         srp_session_t   *p_srp_session = (srp_session_t* __ptr64)p_cm_dreq_rec->qp_context;\r
277         srp_hba_t       *p_hba = p_srp_session->p_hba;\r
278         ib_cm_drep_t    cm_drep;\r
279         ib_api_status_t status;\r
280         int             i;\r
281         int             retry_count = 0;\r
282 \r
283         SRP_ENTER( SRP_DBG_PNP );\r
284 \r
285         SRP_TRACE( SRP_DBG_DEBUG,\r
286                 ("Target has issued a disconnect request.\n") );\r
287 \r
288         if ( p_hba->adapter_paused == FALSE )\r
289         {\r
290                 p_hba->adapter_paused = TRUE;\r
291                 StorPortBusy( p_hba->p_ext, (ULONG)-1 );\r
292                 StorPortCompleteRequest( p_hba->p_ext,\r
293                                                                  SP_UNTAGGED,\r
294                                                                  SP_UNTAGGED,\r
295                                                                  SP_UNTAGGED,\r
296                                                                  SRB_STATUS_BUSY );\r
297                 SRP_TRACE( SRP_DBG_DEBUG, ("Pausing Adapter for %s.\n", p_hba->ioc_info.profile.id_string) );\r
298         }\r
299 \r
300         cl_obj_lock( &p_srp_session->obj );\r
301         p_srp_session->connection.state = SRP_TARGET_DISCONNECTING;\r
302         cl_obj_unlock( &p_srp_session->obj );\r
303 \r
304         cm_drep.p_drep_pdata = NULL;\r
305         cm_drep.drep_length = 0;\r
306 \r
307         status = p_hba->ifc.cm_drep( p_cm_dreq_rec->h_cm_dreq, &cm_drep );\r
308         if ( status != IB_SUCCESS )\r
309         {\r
310                 SRP_TRACE( SRP_DBG_ERROR,\r
311                         ("Cannot respond to target disconnect request. Status = %d\n", status) );\r
312         }\r
313 \r
314         cl_obj_lock( &p_hba->obj );\r
315 \r
316         for ( i = 0; i < SRP_MAX_SERVICE_ENTRIES; i++ )\r
317         {\r
318                 if ( p_srp_session == p_hba->session_list[i] )\r
319                 {\r
320                         p_hba->session_list[i] = NULL;\r
321                         break;\r
322                 }\r
323         }\r
324 \r
325         cl_obj_unlock( &p_hba->obj );\r
326 \r
327         SRP_TRACE( SRP_DBG_VERBOSE, ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );\r
328         cl_obj_destroy( &p_srp_session->obj );\r
329 \r
330         do\r
331         {\r
332                 retry_count++;\r
333 \r
334                 SRP_TRACE( SRP_DBG_DEBUG,\r
335                         ("Attempting to reconnect %s. Connection Attempt Count = %d.\n",\r
336                          p_hba->ioc_info.profile.id_string,\r
337                          retry_count) );\r
338 \r
339                 SRP_TRACE( SRP_DBG_VERBOSE,\r
340                         ("Creating New Session For Service Entry Index %d.\n", p_hba->ioc_info.profile.num_svc_entries));\r
341                 p_srp_session = srp_new_session( p_hba,\r
342                                                                                  p_hba->ioc_info.profile.ioc_guid,\r
343                                                                                  &p_hba->p_svc_entries[i],\r
344                                                                                  &status );\r
345                 if ( p_srp_session == NULL )\r
346                 {\r
347                         status = IB_INSUFFICIENT_MEMORY;\r
348                         break;\r
349                 }\r
350 \r
351                 SRP_TRACE( SRP_DBG_VERBOSE,\r
352                         ("New Session For Service Entry Index %d Created.\n", p_hba->ioc_info.profile.num_svc_entries));\r
353                 SRP_TRACE( SRP_DBG_VERBOSE,\r
354                         ("Logging Into Session.\n"));\r
355                 status = srp_session_login( p_srp_session );\r
356                 if ( status == IB_SUCCESS )\r
357                 {\r
358                         if ( p_hba->max_sg > p_srp_session->connection.max_scatter_gather_entries )\r
359                         {\r
360                                 p_hba->max_sg = p_srp_session->connection.max_scatter_gather_entries;\r
361                         }\r
362 \r
363                         if ( p_hba->max_srb_ext_sz > p_srp_session->connection.init_to_targ_iu_sz )\r
364                         {\r
365                                 p_hba->max_srb_ext_sz =\r
366                                         sizeof( srp_send_descriptor_t ) -\r
367                                         SRP_MIN_IU_SIZE +\r
368                                         p_srp_session->connection.init_to_targ_iu_sz;\r
369                         }\r
370 \r
371                         cl_obj_lock( &p_hba->obj );\r
372                         p_hba->session_list[i] = p_srp_session;\r
373                         cl_obj_unlock( &p_hba->obj );\r
374 \r
375                         SRP_TRACE( SRP_DBG_VERBOSE,\r
376                                 ("Session Login Issued Successfully.\n"));\r
377                 }\r
378                 else\r
379                 {\r
380                         SRP_TRACE( SRP_DBG_ERROR,\r
381                                 ("Session Login Failure Status = %d.\n", status));\r
382                         SRP_TRACE( SRP_DBG_VERBOSE, ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );\r
383                         cl_obj_destroy( &p_srp_session->obj );\r
384                 }\r
385         } while ( (status != IB_SUCCESS) && (retry_count < 3) );\r
386 \r
387         if ( status == IB_SUCCESS )\r
388         {\r
389                 SRP_TRACE( SRP_DBG_DEBUG, ("Resuming Adapter for %s.\n", p_hba->ioc_info.profile.id_string) );\r
390                 p_hba->adapter_paused = FALSE;\r
391                 StorPortReady( p_hba->p_ext );\r
392 //              StorPortNotification( BusChangeDetected, p_hba->p_ext, 0 );\r
393         }\r
394 \r
395         SRP_EXIT( SRP_DBG_PNP );\r
396 }\r
397 \r
398 /* __srp_cm_reply_cb */\r
399 /*!\r
400 Callback for connect reply from the target\r
401 The target has accepted our connect/login request\r
402 \r
403 @param p_cm_reply - pointer to the connect reply structure\r
404 \r
405 @return - none\r
406 */\r
407 static\r
408 void\r
409 __srp_cm_reply_cb(\r
410         IN  ib_cm_rep_rec_t     *p_cm_reply)\r
411 {\r
412         srp_session_t       *p_srp_session = (srp_session_t* __ptr64)p_cm_reply->qp_context;\r
413         srp_connection_t    *p_connection;\r
414         srp_login_rsp_t     *p_srp_login_rsp = (srp_login_rsp_t* __ptr64)p_cm_reply->p_rep_pdata;\r
415         ib_api_status_t     status;\r
416         ib_cm_mra_t         cm_mra;\r
417         ib_cm_rtu_t         cm_rtu;\r
418         cl_status_t         cl_status;\r
419         ib_al_ifc_t                     *p_ifc;\r
420 \r
421         SRP_ENTER( SRP_DBG_PNP );\r
422 \r
423         p_ifc = &p_srp_session->p_hba->ifc;\r
424         p_connection = &p_srp_session->connection;\r
425 \r
426         set_srp_login_response_from_network_to_host( p_srp_login_rsp );\r
427 \r
428         p_connection->request_limit      =\r
429                 MIN( get_srp_login_response_request_limit_delta( p_srp_login_rsp ), SRP_DEFAULT_RECV_Q_DEPTH );\r
430         p_connection->send_queue_depth   = p_connection->request_limit;\r
431         p_connection->recv_queue_depth   = p_connection->request_limit;\r
432         p_connection->init_to_targ_iu_sz = get_srp_login_response_max_init_to_targ_iu( p_srp_login_rsp );\r
433         p_connection->targ_to_init_iu_sz = get_srp_login_response_max_targ_to_init_iu( p_srp_login_rsp );\r
434 \r
435         p_connection->signaled_send_completion_count  = p_connection->send_queue_depth / 2;\r
436         p_connection->max_scatter_gather_entries      =\r
437                 (p_connection->init_to_targ_iu_sz - offsetof( srp_cmd_t, additional_cdb )) / sizeof( srp_memory_descriptor_t );\r
438 \r
439         SRP_TRACE( SRP_DBG_DEBUG,\r
440                         ("Request Limit = %d, SendQ Depth = %d, RecvQDepth = %d, ItoT size = %d, TtoI size = %d, Max S/G = %d\n",\r
441                         p_connection->request_limit,\r
442                         p_connection->send_queue_depth,\r
443                         p_connection->recv_queue_depth,\r
444                         p_connection->init_to_targ_iu_sz,\r
445                         p_connection->targ_to_init_iu_sz,\r
446                         p_connection->max_scatter_gather_entries) );\r
447 \r
448         cm_mra.svc_timeout = 0x08;\r
449         cm_mra.p_mra_pdata = NULL;\r
450         cm_mra.mra_length = 0;\r
451 \r
452         status = p_ifc->cm_mra( p_cm_reply->h_cm_rep, &cm_mra );\r
453         if ( status != IB_SUCCESS )\r
454         {\r
455                 SRP_TRACE( SRP_DBG_ERROR,\r
456                         ("Cannot Send MRA. Status = %d\n", status) );\r
457                 p_connection->state = SRP_CONNECT_FAILURE;\r
458                 goto exit;\r
459         }\r
460 \r
461         status = p_ifc->modify_cq( p_connection->h_send_cq, &p_connection->send_queue_depth );\r
462         if ( status != IB_SUCCESS )\r
463         {\r
464                 SRP_TRACE( SRP_DBG_WARN,\r
465                         ("Cannot Modify Send Completion Queue Depth. Status = %d\n", status) );\r
466         }\r
467 \r
468         status = p_ifc->modify_cq( p_connection->h_recv_cq, &p_connection->recv_queue_depth );\r
469         if ( status != IB_SUCCESS )\r
470         {\r
471                 SRP_TRACE( SRP_DBG_WARN,\r
472                         ("Cannot Modify Recv Completion Queue Depth. Status = %d\n", status) );\r
473         }\r
474 \r
475         cl_status = __srp_create_wc_free_list( p_connection, (p_connection->request_limit * 2) );/* Send/Recv */\r
476         if ( cl_status != CL_SUCCESS )\r
477         {\r
478                 p_connection->state = SRP_CONNECT_FAILURE;\r
479                 goto exit;\r
480         }\r
481 \r
482         status = srp_init_descriptors( &p_srp_session->descriptors,\r
483                                                                    p_connection->request_limit,\r
484                                                                    p_connection->targ_to_init_iu_sz,\r
485                                                                    &p_srp_session->p_hba->ifc,\r
486                                                                    p_srp_session->hca.h_pd,\r
487                                                                    p_connection->h_qp );\r
488         if ( status != IB_SUCCESS )\r
489         {\r
490                 cl_free( p_connection->p_wc_array );\r
491                 p_connection->p_wc_array = NULL;\r
492                 p_connection->p_wc_free_list = NULL;\r
493                 p_connection->state = SRP_CONNECT_FAILURE;\r
494                 goto exit;\r
495         }\r
496 \r
497         cm_rtu.access_ctrl = IB_AC_LOCAL_WRITE | IB_AC_RDMA_READ | IB_AC_RDMA_WRITE;\r
498 \r
499         /* Have to set to 0 to indicate not to modify because Tavor doesn't support this */\r
500         cm_rtu.sq_depth = 0 /*p_connection->request_limit*/;\r
501         cm_rtu.rq_depth = 0 /*p_connection->request_limit*/;\r
502 \r
503         cm_rtu.p_rtu_pdata = NULL;\r
504         cm_rtu.rtu_length = 0;\r
505         cm_rtu.pfn_cm_apr_cb = __srp_cm_apr_cb;\r
506         cm_rtu.pfn_cm_dreq_cb = __srp_cm_dreq_cb;\r
507 \r
508         status = p_ifc->cm_rtu( p_cm_reply->h_cm_rep, &cm_rtu );\r
509         if ( status != IB_SUCCESS )\r
510         {\r
511                 SRP_TRACE( SRP_DBG_ERROR,\r
512                         ("Cannot Send RTU. Status = %d\n", status) );\r
513                 p_connection->state = SRP_CONNECT_FAILURE;\r
514                 goto exit;\r
515         }\r
516 \r
517         p_connection->state = SRP_CONNECTED;\r
518 \r
519         status = p_ifc->rearm_cq( p_connection->h_send_cq, FALSE );\r
520         if ( status != IB_SUCCESS)\r
521         {\r
522                 SRP_TRACE( SRP_DBG_ERROR,\r
523                         ("ib_rearm_cq() for send cq failed!, status 0x%x", status) );\r
524 \r
525                 // TODO: Kill session and inform port driver link down storportnotification\r
526                 return;\r
527         }\r
528 \r
529         status = p_ifc->rearm_cq( p_connection->h_recv_cq, FALSE );\r
530         if ( status != IB_SUCCESS)\r
531         {\r
532                 SRP_TRACE( SRP_DBG_ERROR,\r
533                         ("ib_rearm_cq() for recv failed!, status 0x%x", status) );\r
534 \r
535                 // TODO: Kill session and inform port driver link down storportnotification\r
536                 return;\r
537         }\r
538 \r
539 \r
540 exit:\r
541         cl_status = cl_event_signal( &p_connection->conn_req_event );\r
542 \r
543         SRP_EXIT( SRP_DBG_PNP );\r
544 }\r
545 \r
546 \r
547 /* __srp_cm_rej_cb */\r
548 /*!\r
549 Callback for connect reject from the target\r
550 The target has rejected our connect/login request\r
551 \r
552 @param p_cm_reject - pointer to the connect reject structure\r
553 \r
554 @return - none\r
555 */\r
556 static\r
557 void\r
558 __srp_cm_rej_cb(\r
559         IN  ib_cm_rej_rec_t     *p_cm_reject)\r
560 {\r
561         srp_session_t       *p_srp_session = (srp_session_t* __ptr64)p_cm_reject->qp_context;\r
562         srp_connection_t    *p_connection;\r
563         srp_login_rej_t     *p_srp_login_rej = (srp_login_rej_t* __ptr64)p_cm_reject->p_rej_pdata;\r
564         cl_status_t         cl_status;\r
565 \r
566         SRP_ENTER( SRP_DBG_PNP );\r
567 \r
568         p_connection = &p_srp_session->connection;\r
569 \r
570         if( p_srp_login_rej )\r
571         {\r
572                 set_srp_login_reject_from_network_to_host( p_srp_login_rej ); // <-- Is this coming back NULL?\r
573 \r
574                 SRP_TRACE( SRP_DBG_ERROR,\r
575                         ("Login Rejected. IBT Code = 0x%x, SRP Code = 0x%x\n",\r
576                         p_cm_reject->rej_status,\r
577                         get_srp_login_reject_reason( p_srp_login_rej ) ) );\r
578         }\r
579         else\r
580         {\r
581                 SRP_TRACE( SRP_DBG_ERROR,\r
582                         ("Login Rejected. IBT Code = 0x%x\n",\r
583                         p_cm_reject->rej_status) );\r
584 }\r
585         p_connection->state = SRP_CONNECT_FAILURE;\r
586 \r
587         cl_status = cl_event_signal( &p_connection->conn_req_event );\r
588 \r
589         SRP_EXIT( SRP_DBG_PNP );\r
590 }\r
591 \r
592 /* __srp_issue_session_login */\r
593 /*!\r
594 Initializes and issues a login/cm connect request to the target\r
595 \r
596 @param p_connection   - pointer to the connection structure\r
597 @param p_hca          - pointer to the hca structure used by this connection\r
598 @param send_msg_depth - initial request limit delta value\r
599 \r
600 @return - result of login/cm connect request operations\r
601 */\r
602 #pragma optimize( "", off )\r
603 static\r
604 ib_api_status_t\r
605 __srp_issue_session_login(\r
606         IN OUT  srp_connection_t    *p_connection,\r
607         IN      srp_hca_t           *p_hca,\r
608         IN      uint8_t             send_msg_depth )\r
609 {\r
610         ib_api_status_t status;\r
611         ib_cm_req_t     cm_req;\r
612         srp_login_req_t login_req;\r
613 \r
614         SRP_ENTER( SRP_DBG_PNP );\r
615 \r
616         cl_memclr( &cm_req, sizeof(ib_cm_req_t) );\r
617 \r
618         cm_req.svc_id = p_connection->service_id;\r
619 \r
620         cm_req.flags = 0; // event used instead of IB_FLAGS_SYNC\r
621         cm_req.max_cm_retries = 8;\r
622         cm_req.p_primary_path = p_connection->p_path_rec;\r
623 \r
624         /*\r
625            Build SRP Login request\r
626          */\r
627         setup_srp_login_request( &login_req,\r
628                                                          0, /* tag */\r
629                                                          SRP_MAX_IU_SIZE,\r
630                                                          DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR,\r
631                                                          MCA_TERMINATE_EXISTING,\r
632                                                          &p_connection->init_port_id,\r
633                                                          &p_connection->targ_port_id );\r
634         set_srp_login_request_from_host_to_network(&login_req);\r
635 \r
636         cm_req.p_req_pdata = (const uint8_t *)&login_req;\r
637         cm_req.req_length = (uint8_t)get_srp_login_request_length( &login_req );\r
638 \r
639         cm_req.qp_type = IB_QPT_RELIABLE_CONN;\r
640         cm_req.h_qp = p_connection->h_qp;\r
641 \r
642          /* The maximum number of outstanding RDMA read/atomic operations. */\r
643         status = srp_get_responder_resources( p_hca, &cm_req.resp_res );\r
644         if ( status != IB_SUCCESS )\r
645         {\r
646                 goto exit;\r
647         }\r
648 \r
649         cm_req.init_depth = send_msg_depth;\r
650 \r
651         cm_req.remote_resp_timeout = 15;\r
652         cm_req.flow_ctrl = FALSE;\r
653         cm_req.local_resp_timeout = 16;\r
654         cm_req.retry_cnt = 1;\r
655         cm_req.rnr_nak_timeout = 0; /* 655.36 ms */\r
656         cm_req.rnr_retry_cnt = 6;\r
657 \r
658         cm_req.pfn_cm_rep_cb = __srp_cm_reply_cb;\r
659         cm_req.pfn_cm_req_cb = NULL; /* Set only for P2P */\r
660         cm_req.pfn_cm_mra_cb = __srp_cm_mra_cb;\r
661         cm_req.pfn_cm_rej_cb = __srp_cm_rej_cb;\r
662 \r
663         cm_req.pkey = p_connection->p_path_rec->pkey;\r
664 \r
665         status = p_hca->p_hba->ifc.cm_req( &cm_req );\r
666         if ( status == IB_SUCCESS )\r
667         {\r
668                 p_connection->state = SRP_CONNECT_REQUESTED;\r
669         }\r
670         else\r
671         {\r
672                 SRP_TRACE( SRP_DBG_ERROR,\r
673                         ("Cannot Send Connect Request. Status = %d\n", status) );\r
674                 p_connection->state = SRP_CONNECT_FAILURE;\r
675         }\r
676 \r
677 exit:\r
678         SRP_EXIT( SRP_DBG_PNP );\r
679 \r
680         return ( status );\r
681 }\r
682 #pragma optimize( "", on )\r
683 \r
684 /* srp_init_connection */\r
685 /*!\r
686 Initializes a connection structure\r
687 \r
688 @param p_connection   - pointer to the connection structure\r
689 @param p_path_rec     - pointer to the path to the target\r
690 @param p_targ_port_id - pointer to the target port id to which we want to connect\r
691 @param service_id     - service id to which we want to connect\r
692 \r
693 @return - always success (for now)\r
694 */\r
695 ib_api_status_t\r
696 srp_init_connection(\r
697         IN OUT  srp_connection_t        *p_connection,\r
698         IN      ib_path_rec_t           *p_path_rec,\r
699         IN      srp_ib_targ_port_id_t   *p_targ_port_id,\r
700         IN      ib_net64_t              service_id )\r
701 {\r
702         SRP_ENTER( SRP_DBG_PNP );\r
703 \r
704         cl_memclr( p_connection, sizeof(*p_connection) );\\r
705 \r
706         p_connection->initialized = TRUE;\r
707 \r
708         p_connection->state = SRP_NOT_CONNECTED;\r
709 \r
710         p_connection->p_path_rec = p_path_rec;\r
711         p_connection->targ_port_id = *p_targ_port_id;\r
712         p_connection->service_id = service_id;\r
713         p_connection->send_queue_depth = SRP_DEFAULT_SEND_Q_DEPTH;\r
714         p_connection->recv_queue_depth = SRP_DEFAULT_RECV_Q_DEPTH;\r
715 \r
716         SRP_EXIT( SRP_DBG_PNP );\r
717 \r
718         return ( IB_SUCCESS );\r
719 }\r
720 \r
721 /* srp_connect */\r
722 /*!\r
723 Orchestrates the processing required to connect to a target device\r
724 \r
725 @param p_connection        - pointer to the connection structure\r
726 @param p_hca               - pointer to the hca structure used by this connection\r
727 @param initiator_extension - value used for id_extension of the initiator port id\r
728 @param send_msg_depth      - initial request limit delta value\r
729 @param p_session           - context passed to callback functions\r
730 \r
731 @return -  result of connect operations\r
732 */\r
733 ib_api_status_t\r
734 srp_connect(\r
735         IN OUT  srp_connection_t    *p_connection,\r
736         IN      srp_hca_t           *p_hca,\r
737         IN      uint64_t            initiator_extension,\r
738         IN      uint8_t             send_msg_depth,\r
739         IN      p_srp_session_t     p_session )\r
740 {\r
741         ib_api_status_t status;\r
742         cl_status_t     cl_status;\r
743 \r
744         SRP_ENTER( SRP_DBG_PNP );\r
745 \r
746         p_connection->init_port_id.guid = p_hca->ca_guid;\r
747         p_connection->init_port_id.id_extension = initiator_extension;\r
748 \r
749         status = __srp_create_cqs( p_connection, p_hca, p_session );\r
750         if ( status != IB_SUCCESS )\r
751         {\r
752                 goto exit;\r
753         }\r
754 \r
755         status = __srp_create_qp( p_connection, p_hca, p_session );\r
756         if ( status != IB_SUCCESS )\r
757         {\r
758                 goto exit;\r
759         }\r
760 \r
761         cl_status = cl_event_init( &p_connection->conn_req_event, TRUE );\r
762         if ( cl_status != CL_SUCCESS )\r
763         {\r
764                 SRP_TRACE( SRP_DBG_ERROR,\r
765                         ("Cannot Initialize Connect Request Event. Status = %d\n", cl_status) );\r
766                 status = cl_status;\r
767                 goto exit;\r
768         }\r
769 \r
770         status = __srp_issue_session_login( p_connection, p_hca, send_msg_depth );\r
771         if ( status != IB_SUCCESS )\r
772         {\r
773                 cl_event_destroy( &p_connection->conn_req_event );\r
774                 goto exit;\r
775         }\r
776 \r
777         cl_status = cl_event_wait_on( &p_connection->conn_req_event, EVENT_NO_TIMEOUT, FALSE );\r
778         if ( cl_status != CL_SUCCESS )\r
779         {\r
780                 SRP_TRACE( SRP_DBG_ERROR,\r
781                         ("Wait On Connect Request Event Failed. Status = %d\n", cl_status) );\r
782                 status = cl_status;\r
783                 cl_event_destroy( &p_connection->conn_req_event );\r
784                 goto exit;\r
785         }\r
786 \r
787         cl_event_destroy( &p_connection->conn_req_event );\r
788 \r
789         if ( p_connection->state != SRP_CONNECTED )\r
790         {\r
791                 status = IB_ERROR;\r
792                 goto exit;\r
793         }\r
794 \r
795 exit:\r
796         SRP_EXIT( SRP_DBG_PNP );\r
797 \r
798         return ( status );\r
799 }\r
800 \r
801 /* srp_free_connection */\r
802 /*!\r
803 Frees connection resources\r
804 \r
805 @param p_connection  - pointer to the connection structure\r
806 \r
807 @return -  none\r
808 */\r
809 void\r
810 srp_free_connection(\r
811         IN  srp_connection_t    *p_srp_connection )\r
812 {\r
813         SRP_ENTER( SRP_DBG_PNP );\r
814 \r
815         if ( p_srp_connection->initialized == TRUE )\r
816         {\r
817                 if ( p_srp_connection->p_wc_array != NULL )\r
818                 {\r
819                         cl_free( p_srp_connection->p_wc_array );\r
820                 }\r
821 \r
822                 cl_event_destroy( &p_srp_connection->conn_req_event );\r
823 \r
824                 cl_memclr( p_srp_connection, sizeof( *p_srp_connection ) );\r
825         }\r
826 \r
827         SRP_EXIT( SRP_DBG_PNP );\r
828 }\r
829 \r