8f86b3670c37d815f071b6e4d8beecd8a81f6e35
[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         union\r
417         {\r
418                 ib_cm_mra_t             cm_mra;\r
419                 ib_cm_rtu_t             cm_rtu;\r
420                 ib_cm_rej_t             cm_rej;\r
421 \r
422         }       u;\r
423         cl_status_t                     cl_status;\r
424         ib_al_ifc_t                     *p_ifc;\r
425 \r
426         SRP_ENTER( SRP_DBG_PNP );\r
427 \r
428         p_ifc = &p_srp_session->p_hba->ifc;\r
429         p_connection = &p_srp_session->connection;\r
430 \r
431         set_srp_login_response_from_network_to_host( p_srp_login_rsp );\r
432         p_connection->descriptor_format = get_srp_login_response_supported_data_buffer_formats( p_srp_login_rsp );\r
433 \r
434         p_connection->request_limit      =\r
435                 MIN( get_srp_login_response_request_limit_delta( p_srp_login_rsp ), SRP_DEFAULT_RECV_Q_DEPTH );\r
436         p_connection->send_queue_depth   = p_connection->request_limit;\r
437         p_connection->recv_queue_depth   = p_connection->request_limit;\r
438         p_connection->init_to_targ_iu_sz = get_srp_login_response_max_init_to_targ_iu( p_srp_login_rsp );\r
439         p_connection->targ_to_init_iu_sz = get_srp_login_response_max_targ_to_init_iu( p_srp_login_rsp );\r
440 \r
441         p_connection->signaled_send_completion_count  = p_connection->send_queue_depth / 2;\r
442         \r
443         if (( p_connection->descriptor_format & DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS ) == DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS )\r
444         {\r
445                 p_connection->max_scatter_gather_entries =\r
446                                 ( 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
447         }\r
448         else if (( p_connection->descriptor_format & DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR ) == DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR )\r
449         {\r
450                 p_connection->max_scatter_gather_entries = \r
451                                 (p_connection->init_to_targ_iu_sz - offsetof( srp_cmd_t, additional_cdb ))/ sizeof( srp_memory_descriptor_t );\r
452         }\r
453         else /* not reported any descriptor format */\r
454         {\r
455                 SRP_TRACE( SRP_DBG_DEBUG,(" Target does not support valid descriptor formats\n") );\r
456                 goto rej;\r
457         }\r
458         SRP_TRACE( SRP_DBG_DEBUG,\r
459                         ("Request Limit = %d, SendQ Depth = %d, RecvQDepth = %d, ItoT size = %d, TtoI size = %d, Max S/G = %d\n",\r
460                         p_connection->request_limit,\r
461                         p_connection->send_queue_depth,\r
462                         p_connection->recv_queue_depth,\r
463                         p_connection->init_to_targ_iu_sz,\r
464                         p_connection->targ_to_init_iu_sz,\r
465                         p_connection->max_scatter_gather_entries) );\r
466 \r
467         u.cm_mra.svc_timeout = 0x08;\r
468         u.cm_mra.p_mra_pdata = NULL;\r
469         u.cm_mra.mra_length = 0;\r
470 \r
471         status = p_ifc->cm_mra( p_cm_reply->h_cm_rep, &u.cm_mra );\r
472         if ( status != IB_SUCCESS )\r
473         {\r
474                 SRP_TRACE( SRP_DBG_ERROR,\r
475                         ("Cannot Send MRA. Status = %d\n", status) );\r
476                 goto rej;\r
477         }\r
478 \r
479         status = p_ifc->modify_cq( p_connection->h_send_cq, &p_connection->send_queue_depth );\r
480         if ( status != IB_SUCCESS )\r
481         {\r
482                 SRP_TRACE( SRP_DBG_WARN,\r
483                         ("Cannot Modify Send Completion Queue Depth. Status = %d\n", status) );\r
484         }\r
485 \r
486         status = p_ifc->modify_cq( p_connection->h_recv_cq, &p_connection->recv_queue_depth );\r
487         if ( status != IB_SUCCESS )\r
488         {\r
489                 SRP_TRACE( SRP_DBG_WARN,\r
490                         ("Cannot Modify Recv Completion Queue Depth. Status = %d\n", status) );\r
491         }\r
492 \r
493         cl_status = __srp_create_wc_free_list( p_connection, (p_connection->request_limit * 2) );/* Send/Recv */\r
494         if ( cl_status != CL_SUCCESS )\r
495         {\r
496                 goto rej;\r
497         }\r
498 \r
499         status = srp_init_descriptors( &p_srp_session->descriptors,\r
500                                                                    p_connection->request_limit,\r
501                                                                    p_connection->targ_to_init_iu_sz,\r
502                                                                    &p_srp_session->p_hba->ifc,\r
503                                                                    p_srp_session->hca.h_pd,\r
504                                                                    p_connection->h_qp );\r
505         if ( status != IB_SUCCESS )\r
506         {\r
507                 cl_free( p_connection->p_wc_array );\r
508                 p_connection->p_wc_array = NULL;\r
509                 p_connection->p_wc_free_list = NULL;\r
510 rej:\r
511                 p_connection->state = SRP_CONNECT_FAILURE;\r
512                 cl_memclr( &u.cm_rej, sizeof(u.cm_rej) );\r
513                 u.cm_rej.rej_status = IB_REJ_INSUF_RESOURCES;\r
514                 p_ifc->cm_rej( p_cm_reply->h_cm_rep, &u.cm_rej );\r
515                 goto exit;\r
516         }\r
517 \r
518         u.cm_rtu.access_ctrl = IB_AC_LOCAL_WRITE | IB_AC_RDMA_READ | IB_AC_RDMA_WRITE;\r
519 \r
520         /* Have to set to 0 to indicate not to modify because Tavor doesn't support this */\r
521         u.cm_rtu.sq_depth = 0 /*p_connection->request_limit*/;\r
522         u.cm_rtu.rq_depth = 0 /*p_connection->request_limit*/;\r
523 \r
524         u.cm_rtu.p_rtu_pdata = NULL;\r
525         u.cm_rtu.rtu_length = 0;\r
526         u.cm_rtu.pfn_cm_apr_cb = __srp_cm_apr_cb;\r
527         u.cm_rtu.pfn_cm_dreq_cb = __srp_cm_dreq_cb;\r
528 \r
529         status = p_ifc->cm_rtu( p_cm_reply->h_cm_rep, &u.cm_rtu );\r
530         if ( status != IB_SUCCESS )\r
531         {\r
532                 SRP_TRACE( SRP_DBG_ERROR,\r
533                         ("Cannot Send RTU. Status = %d\n", status) );\r
534                 p_connection->state = SRP_CONNECT_FAILURE;\r
535                 goto exit;\r
536         }\r
537 \r
538         p_connection->state = SRP_CONNECTED;\r
539 \r
540         status = p_ifc->rearm_cq( p_connection->h_send_cq, FALSE );\r
541         if ( status != IB_SUCCESS)\r
542         {\r
543                 SRP_TRACE( SRP_DBG_ERROR,\r
544                         ("ib_rearm_cq() for send cq failed!, status 0x%x", status) );\r
545 \r
546                 // TODO: Kill session and inform port driver link down storportnotification\r
547                 return;\r
548         }\r
549 \r
550         status = p_ifc->rearm_cq( p_connection->h_recv_cq, FALSE );\r
551         if ( status != IB_SUCCESS)\r
552         {\r
553                 SRP_TRACE( SRP_DBG_ERROR,\r
554                         ("ib_rearm_cq() for recv failed!, status 0x%x", status) );\r
555 \r
556                 // TODO: Kill session and inform port driver link down storportnotification\r
557                 return;\r
558         }\r
559 \r
560 \r
561 exit:\r
562         cl_status = cl_event_signal( &p_connection->conn_req_event );\r
563 \r
564         SRP_EXIT( SRP_DBG_PNP );\r
565 }\r
566 \r
567 \r
568 /* __srp_cm_rej_cb */\r
569 /*!\r
570 Callback for connect reject from the target\r
571 The target has rejected our connect/login request\r
572 \r
573 @param p_cm_reject - pointer to the connect reject structure\r
574 \r
575 @return - none\r
576 */\r
577 static\r
578 void\r
579 __srp_cm_rej_cb(\r
580         IN  ib_cm_rej_rec_t     *p_cm_reject)\r
581 {\r
582         srp_session_t       *p_srp_session = (srp_session_t* __ptr64)p_cm_reject->qp_context;\r
583         srp_connection_t    *p_connection;\r
584         srp_login_rej_t     *p_srp_login_rej = (srp_login_rej_t* __ptr64)p_cm_reject->p_rej_pdata;\r
585         cl_status_t         cl_status;\r
586 \r
587         SRP_ENTER( SRP_DBG_PNP );\r
588 \r
589         p_connection = &p_srp_session->connection;\r
590 \r
591         if( p_srp_login_rej )\r
592         {\r
593                 set_srp_login_reject_from_network_to_host( p_srp_login_rej ); // <-- Is this coming back NULL?\r
594                 p_connection->reject_reason = get_srp_login_reject_reason( p_srp_login_rej );\r
595 \r
596                 SRP_TRACE( SRP_DBG_ERROR,\r
597                         ("Login Rejected. IBT Code = 0x%x, SRP Code = 0x%x\n",\r
598                         p_cm_reject->rej_status, p_connection->reject_reason ) );\r
599                 switch( p_connection->reject_reason )\r
600                 {\r
601                         case LIREJ_INIT_TO_TARG_IU_LENGTH_TOO_LARGE:\r
602                                 SRP_TRACE( SRP_DBG_ERROR, ("REQUESTED IU_SIZE %d\n", p_connection->req_max_iu_msg_size ));\r
603                                 break;\r
604                         case LIREJ_UNSUPPORTED_DATA_BUFFER_DESCRIPTOR_FORMAT:\r
605                                 SRP_TRACE( SRP_DBG_ERROR, ("REQUESTED DESC FORMAT: %#x, SUPPORTED FORMAT %#x\n",\r
606                                         p_connection->descriptor_format, \r
607                                         get_srp_login_reject_supported_data_buffer_formats(p_srp_login_rej) ));\r
608                                         __srp_issue_session_login( p_connection, (srp_hca_t *)&p_srp_session->hca, p_connection->ioc_max_send_msg_depth );\r
609                                         return;\r
610                         default:\r
611                                 break;\r
612                 }\r
613         }\r
614         else\r
615         {\r
616                 SRP_TRACE( SRP_DBG_ERROR,\r
617                         ("Login Rejected. IBT Code = 0x%x\n",\r
618                         p_cm_reject->rej_status) );\r
619 }\r
620         p_connection->state = SRP_CONNECT_FAILURE;\r
621 \r
622         cl_status = cl_event_signal( &p_connection->conn_req_event );\r
623 \r
624         SRP_EXIT( SRP_DBG_PNP );\r
625 }\r
626 \r
627 /* __srp_issue_session_login */\r
628 /*!\r
629 Initializes and issues a login/cm connect request to the target\r
630 \r
631 @param p_connection   - pointer to the connection structure\r
632 @param p_hca          - pointer to the hca structure used by this connection\r
633 @param send_msg_depth - initial request limit delta value\r
634 \r
635 @return - result of login/cm connect request operations\r
636 */\r
637 #pragma optimize( "", off )\r
638 static\r
639 ib_api_status_t\r
640 __srp_issue_session_login(\r
641         IN OUT  srp_connection_t    *p_connection,\r
642         IN      srp_hca_t           *p_hca,\r
643         IN      uint8_t             send_msg_depth )\r
644 {\r
645         ib_api_status_t status;\r
646         ib_cm_req_t     cm_req;\r
647         srp_login_req_t login_req;\r
648 \r
649         SRP_ENTER( SRP_DBG_PNP );\r
650 \r
651         cl_memclr( &cm_req, sizeof(ib_cm_req_t) );\r
652 \r
653         cm_req.svc_id = p_connection->service_id;\r
654 \r
655         cm_req.flags = 0; // event used instead of IB_FLAGS_SYNC\r
656         cm_req.max_cm_retries = 8;\r
657         cm_req.p_primary_path = p_connection->p_path_rec;\r
658         \r
659         /*already tried to login before and failed ? */\r
660         if ( !p_connection->reject_reason )\r
661         {\r
662                 p_connection->descriptor_format = DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR | DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS;\r
663         }\r
664         else if ( p_connection->reject_reason == LIREJ_UNSUPPORTED_DATA_BUFFER_DESCRIPTOR_FORMAT )\r
665         {\r
666                 p_connection->descriptor_format = DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR;\r
667         }\r
668         else\r
669         {\r
670                 p_connection->state = SRP_CONNECT_FAILURE;\r
671                 status = IB_ERROR;\r
672                 goto exit;\r
673         }\r
674         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
675         /*\r
676            Build SRP Login request\r
677          */\r
678         setup_srp_login_request( &login_req,\r
679                                                          0, /* tag */\r
680                                                          p_connection->req_max_iu_msg_size,\r
681                                                          p_connection->descriptor_format,\r
682                                                          MCA_TERMINATE_EXISTING,\r
683                                                          &p_connection->init_port_id,\r
684                                                          &p_connection->targ_port_id );\r
685         set_srp_login_request_from_host_to_network(&login_req);\r
686 \r
687         cm_req.p_req_pdata = (const uint8_t *)&login_req;\r
688         cm_req.req_length = (uint8_t)get_srp_login_request_length( &login_req );\r
689 \r
690         cm_req.qp_type = IB_QPT_RELIABLE_CONN;\r
691         cm_req.h_qp = p_connection->h_qp;\r
692 \r
693          /* The maximum number of outstanding RDMA read/atomic operations. */\r
694         status = srp_get_responder_resources( p_hca, &cm_req.resp_res );\r
695         if ( status != IB_SUCCESS )\r
696         {\r
697                 goto exit;\r
698         }\r
699 \r
700         cm_req.init_depth = send_msg_depth;\r
701 \r
702         cm_req.remote_resp_timeout = 15;\r
703         cm_req.flow_ctrl = FALSE;\r
704         cm_req.local_resp_timeout = 16;\r
705         cm_req.retry_cnt = 1;\r
706         cm_req.rnr_nak_timeout = 0; /* 655.36 ms */\r
707         cm_req.rnr_retry_cnt = 6;\r
708 \r
709         cm_req.pfn_cm_rep_cb = __srp_cm_reply_cb;\r
710         cm_req.pfn_cm_req_cb = NULL; /* Set only for P2P */\r
711         cm_req.pfn_cm_mra_cb = __srp_cm_mra_cb;\r
712         cm_req.pfn_cm_rej_cb = __srp_cm_rej_cb;\r
713 \r
714         cm_req.pkey = p_connection->p_path_rec->pkey;\r
715 \r
716         status = p_hca->p_hba->ifc.cm_req( &cm_req );\r
717         if ( status == IB_SUCCESS )\r
718         {\r
719                 p_connection->state = SRP_CONNECT_REQUESTED;\r
720         }\r
721         else\r
722         {\r
723                 SRP_TRACE( SRP_DBG_ERROR,\r
724                         ("Cannot Send Connect Request. Status = %d\n", status) );\r
725                 p_connection->state = SRP_CONNECT_FAILURE;\r
726         }\r
727 \r
728 exit:\r
729         SRP_EXIT( SRP_DBG_PNP );\r
730 \r
731         return ( status );\r
732 }\r
733 #pragma optimize( "", on )\r
734 \r
735 /* srp_init_connection */\r
736 /*!\r
737 Initializes a connection structure\r
738 \r
739 @param p_connection   - pointer to the connection structure\r
740 @param p_path_rec     - pointer to the path to the target\r
741 @param p_targ_port_id - pointer to the target port id to which we want to connect\r
742 @param service_id     - service id to which we want to connect\r
743 \r
744 @return - always success (for now)\r
745 */\r
746 ib_api_status_t\r
747 srp_init_connection(\r
748         IN OUT  srp_connection_t        *p_connection,\r
749         IN      ib_path_rec_t           *p_path_rec,\r
750         IN      srp_ib_targ_port_id_t   *p_targ_port_id,\r
751         IN      ib_net64_t              service_id )\r
752 {\r
753         SRP_ENTER( SRP_DBG_PNP );\r
754 \r
755         cl_memclr( p_connection, sizeof(*p_connection) );\\r
756 \r
757         p_connection->initialized = TRUE;\r
758 \r
759         p_connection->state = SRP_NOT_CONNECTED;\r
760 \r
761         p_connection->p_path_rec = p_path_rec;\r
762         p_connection->targ_port_id = *p_targ_port_id;\r
763         p_connection->service_id = service_id;\r
764         p_connection->send_queue_depth = SRP_DEFAULT_SEND_Q_DEPTH;\r
765         p_connection->recv_queue_depth = SRP_DEFAULT_RECV_Q_DEPTH;\r
766 \r
767         SRP_EXIT( SRP_DBG_PNP );\r
768 \r
769         return ( IB_SUCCESS );\r
770 }\r
771 \r
772 /* srp_connect */\r
773 /*!\r
774 Orchestrates the processing required to connect to a target device\r
775 \r
776 @param p_connection        - pointer to the connection structure\r
777 @param p_hca               - pointer to the hca structure used by this connection\r
778 @param initiator_extension - value used for id_extension of the initiator port id\r
779 @param send_msg_depth      - initial request limit delta value\r
780 @param p_session           - context passed to callback functions\r
781 \r
782 @return -  result of connect operations\r
783 */\r
784 ib_api_status_t\r
785 srp_connect(\r
786         IN OUT  srp_connection_t    *p_connection,\r
787         IN      srp_hca_t           *p_hca,\r
788         IN      uint64_t            initiator_extension,\r
789         IN      uint8_t             send_msg_depth,\r
790         IN      p_srp_session_t     p_session )\r
791 {\r
792         ib_api_status_t status;\r
793         cl_status_t     cl_status;\r
794 \r
795         SRP_ENTER( SRP_DBG_PNP );\r
796 \r
797         p_connection->init_port_id.guid = p_hca->ca_guid;\r
798         p_connection->init_port_id.id_extension = initiator_extension;\r
799         p_connection->ioc_max_send_msg_size = cl_ntoh32 (p_session->p_hba->ioc_info.profile.send_msg_size);\r
800         p_connection->ioc_max_send_msg_depth = send_msg_depth;\r
801         p_connection->reject_reason = 0;\r
802 \r
803         status = __srp_create_cqs( p_connection, p_hca, p_session );\r
804         if ( status != IB_SUCCESS )\r
805         {\r
806                 goto exit;\r
807         }\r
808 \r
809         status = __srp_create_qp( p_connection, p_hca, p_session );\r
810         if ( status != IB_SUCCESS )\r
811         {\r
812                 goto exit;\r
813         }\r
814 \r
815         cl_status = cl_event_init( &p_connection->conn_req_event, TRUE );\r
816         if ( cl_status != CL_SUCCESS )\r
817         {\r
818                 SRP_TRACE( SRP_DBG_ERROR,\r
819                         ("Cannot Initialize Connect Request Event. Status = %d\n", cl_status) );\r
820                 status = cl_status;\r
821                 goto exit;\r
822         }\r
823 \r
824         status = __srp_issue_session_login( p_connection, p_hca, send_msg_depth );\r
825         if ( status != IB_SUCCESS )\r
826         {\r
827                 cl_event_destroy( &p_connection->conn_req_event );\r
828                 goto exit;\r
829         }\r
830 \r
831         cl_status = cl_event_wait_on( &p_connection->conn_req_event, EVENT_NO_TIMEOUT, FALSE );\r
832         if ( cl_status != CL_SUCCESS )\r
833         {\r
834                 SRP_TRACE( SRP_DBG_ERROR,\r
835                         ("Wait On Connect Request Event Failed. Status = %d\n", cl_status) );\r
836                 status = cl_status;\r
837                 cl_event_destroy( &p_connection->conn_req_event );\r
838                 goto exit;\r
839         }\r
840 \r
841         cl_event_destroy( &p_connection->conn_req_event );\r
842 \r
843         if ( p_connection->state != SRP_CONNECTED )\r
844         {\r
845                 status = IB_ERROR;\r
846                 goto exit;\r
847         }\r
848 \r
849 exit:\r
850         SRP_EXIT( SRP_DBG_PNP );\r
851 \r
852         return ( status );\r
853 }\r
854 \r
855 /* srp_free_connection */\r
856 /*!\r
857 Frees connection resources\r
858 \r
859 @param p_connection  - pointer to the connection structure\r
860 \r
861 @return -  none\r
862 */\r
863 void\r
864 srp_free_connection(\r
865         IN  srp_connection_t    *p_srp_connection )\r
866 {\r
867         SRP_ENTER( SRP_DBG_PNP );\r
868 \r
869         if ( p_srp_connection->initialized == TRUE )\r
870         {\r
871                 if ( p_srp_connection->p_wc_array != NULL )\r
872                 {\r
873                         cl_free( p_srp_connection->p_wc_array );\r
874                 }\r
875 \r
876                 cl_event_destroy( &p_srp_connection->conn_req_event );\r
877 \r
878                 cl_memclr( p_srp_connection, sizeof( *p_srp_connection ) );\r
879         }\r
880 \r
881         SRP_EXIT( SRP_DBG_PNP );\r
882 }\r
883 \r