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