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