[SRP] Add WPP
[mirror/winof/.git] / ulp / srp / kernel / srp_session.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_debug.h"\r
34 #if defined(EVENT_TRACING)\r
35 #ifdef offsetof\r
36 #undef offsetof\r
37 #endif\r
38 #include "srp_session.tmh"\r
39 #endif\r
40 #include "srp_session.h"\r
41 #include <stdlib.h>\r
42 \r
43 /* __srp_destroying_session */\r
44 /*!\r
45 Called when session has been marked for destruction\r
46 \r
47 @param p_obj - pointer to a session object\r
48 \r
49 @return - none\r
50 */\r
51 static void\r
52 __srp_destroying_session(\r
53         IN  cl_obj_t    *p_obj )\r
54 {\r
55         srp_session_t   *p_srp_session;\r
56 \r
57         SRP_ENTER( SRP_DBG_PNP );\r
58 \r
59         p_srp_session = PARENT_STRUCT( p_obj, srp_session_t, obj );\r
60 \r
61         p_srp_session->connection.state = SRP_CONNECTION_CLOSING;\r
62 \r
63         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
64                 ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );\r
65 \r
66         SRP_EXIT( SRP_DBG_PNP );\r
67 }\r
68 \r
69 \r
70 /* __srp_cleanup_session */\r
71 /*!\r
72 Called when session is being destroyed\r
73 in order to perform resource deallocation\r
74 \r
75 @param p_obj - pointer to a session object\r
76 \r
77 @return - none\r
78 */\r
79 void\r
80 __srp_cleanup_session(\r
81         IN  cl_obj_t    *p_obj )\r
82 {\r
83         srp_session_t   *p_srp_session;\r
84 \r
85         SRP_ENTER( SRP_DBG_PNP );\r
86 \r
87         p_srp_session = PARENT_STRUCT( p_obj, srp_session_t, obj );\r
88 \r
89         srp_close_ca( &p_srp_session->hca );\r
90 \r
91         if ( p_srp_session->p_shutdown_srb != NULL )\r
92         {\r
93                 p_srp_session->p_shutdown_srb->SrbStatus = SRB_STATUS_SUCCESS;\r
94                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
95                         ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), "\r
96                         "Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",\r
97                         g_srb_status_name[p_srp_session->p_shutdown_srb->SrbStatus],\r
98                         p_srp_session->p_shutdown_srb->SrbStatus,\r
99                         g_srb_function_name[p_srp_session->p_shutdown_srb->Function],\r
100                         p_srp_session->p_shutdown_srb->Function,\r
101                         p_srp_session->p_shutdown_srb->PathId,\r
102                         p_srp_session->p_shutdown_srb->TargetId,\r
103                         p_srp_session->p_shutdown_srb->Lun) );\r
104                 StorPortNotification( RequestComplete, p_srp_session->p_hba->p_ext,\r
105                         p_srp_session->p_shutdown_srb );\r
106         }\r
107 \r
108         srp_free_connection( &p_srp_session->connection );\r
109         srp_destroy_descriptors( &p_srp_session->descriptors );\r
110 \r
111         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
112                 ("Session Object ref_cnt = %d\n", p_srp_session->obj.ref_cnt) );\r
113 \r
114         SRP_EXIT( SRP_DBG_PNP );\r
115 }\r
116 \r
117 /* __srp_free_session */\r
118 /*!\r
119 Called when session has been destroyed\r
120 and is ready for deallocation\r
121 \r
122 @param p_obj - pointer to a session object\r
123 \r
124 @return - none\r
125 */\r
126 static void\r
127 __srp_free_session(\r
128         IN  cl_obj_t    *p_obj )\r
129 {\r
130         srp_session_t   *p_srp_session;\r
131 \r
132         SRP_ENTER( SRP_DBG_PNP );\r
133 \r
134         p_srp_session = PARENT_STRUCT( p_obj, srp_session_t, obj );\r
135 \r
136         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
137                 ("Before DeInit Session Object ref_cnt = %d\n",\r
138                 p_srp_session->obj.ref_cnt) );\r
139 \r
140         cl_obj_deinit( p_obj );\r
141 \r
142         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG, \r
143                 ("After DeInit Session Object ref_cnt = %d\n",\r
144                 p_srp_session->obj.ref_cnt) );\r
145 \r
146         cl_free( p_srp_session );\r
147 \r
148         SRP_EXIT( SRP_DBG_PNP );\r
149 }\r
150 \r
151 /* __srp_validate_service_entry */\r
152 /*!\r
153 Validates the format of the Service Name and\r
154 Converts and returns the  id extension encoded\r
155 within the service name string\r
156 \r
157 @param p_svc_entry           - pointer to the service entry\r
158 @param p_target_id_extension - pointer value to hold the returned id extension\r
159 \r
160 @return - result of operation\r
161 */\r
162 static ib_api_status_t\r
163 __srp_validate_service_entry(\r
164         IN      ib_svc_entry_t  *p_svc_entry,\r
165         OUT     uint64_t        *p_target_id_extension )\r
166 {\r
167         ib_api_status_t status = IB_SUCCESS;\r
168         char            target_id_extension[SRP_EXTENSION_ID_LENGTH + 1];\r
169         size_t          target_id_extension_size;\r
170         uint64_t        multiplier = 1;\r
171         ULONG           id_extension;\r
172 \r
173         SRP_ENTER( SRP_DBG_PNP );\r
174 \r
175         if ( cl_memcmp( p_svc_entry->name, SRP_SERVICE_NAME_PREFIX, strlen(SRP_SERVICE_NAME_PREFIX)) != 0 )\r
176         {\r
177                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
178                         ("Service Name Not Properly Formatted.\n") );\r
179                 status = IB_INVALID_SERVICE_TYPE;\r
180                 goto exit;\r
181         }\r
182 \r
183         *p_target_id_extension = 0;\r
184 \r
185         cl_memclr( target_id_extension, sizeof(target_id_extension) );\r
186         cl_memcpy( target_id_extension, &p_svc_entry->name[strlen(SRP_SERVICE_NAME_PREFIX)], 16 );\r
187 \r
188         target_id_extension_size = strlen( target_id_extension );\r
189 \r
190         while ( target_id_extension_size != 0 )\r
191         {\r
192                 char        current_digit[2] = {'\0', '\0'};\r
193                 NTSTATUS    ntstatus;\r
194 \r
195                 target_id_extension_size--;\r
196 \r
197                 current_digit[0] = target_id_extension[target_id_extension_size];\r
198 \r
199                 ntstatus = RtlCharToInteger( current_digit, 16, &id_extension );\r
200                 if ( ntstatus != STATUS_SUCCESS )\r
201                 {\r
202                         SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
203                                 ("Target Id Extension INVALID.\n") );\r
204                         status = IB_INVALID_PARAMETER;\r
205                         break;\r
206                 }\r
207 \r
208                 (*p_target_id_extension) += ( id_extension * multiplier );\r
209 \r
210                 multiplier <<= 4;\r
211         }\r
212 \r
213 exit:\r
214         SRP_EXIT( SRP_DBG_PNP );\r
215 \r
216         return ( status );\r
217 }\r
218 \r
219 /* srp_new_session */\r
220 /*!\r
221 Allocates and initializes a session structure and it's sub-structures\r
222 \r
223 @param p_hba       - pointer to the hba associated with the new session\r
224 @param ioc_guid    - pointer to the target's ioc guid\r
225 @param p_svc_entry - pointer to the service entry\r
226 @param p_status    - pointer to the reason code\r
227 \r
228 @return - Pointer to new session or NULL if failure. See p_status for reason code.\r
229 */\r
230 srp_session_t*\r
231 srp_new_session(\r
232         IN      srp_hba_t       *p_hba,\r
233         IN      ib_net64_t      ioc_guid,\r
234         IN      ib_svc_entry_t  *p_svc_entry,\r
235         OUT     ib_api_status_t *p_status )\r
236 {\r
237         uint64_t                target_id_extension;\r
238         srp_session_t           *p_srp_session = NULL;\r
239         srp_ib_targ_port_id_t   targ_port_id;\r
240         cl_status_t             cl_status;\r
241 \r
242         SRP_ENTER( SRP_DBG_PNP );\r
243 \r
244         *p_status = __srp_validate_service_entry( p_svc_entry, &target_id_extension );\r
245         if ( *p_status != IB_SUCCESS )\r
246         {\r
247                 goto exit;\r
248         }\r
249 \r
250         p_srp_session = (srp_session_t*)cl_zalloc( sizeof(srp_session_t) );\r
251         if ( p_srp_session == NULL )\r
252         {\r
253                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
254                         ("Failed to allocate srp_session_t structure.\n") );\r
255                 *p_status = IB_INSUFFICIENT_MEMORY;\r
256                 goto exit;\r
257         }\r
258 \r
259         p_srp_session->p_hba = p_hba;\r
260 \r
261         targ_port_id.io_ctrl_guid = ioc_guid;\r
262         targ_port_id.id_extension = target_id_extension;\r
263 \r
264         *p_status = srp_init_connection( &p_srp_session->connection,\r
265                                                                          &p_hba->p_srp_path_record->path_rec,\r
266                                                                          &targ_port_id,\r
267                                                                          p_svc_entry->id );\r
268         if ( *p_status != IB_SUCCESS )\r
269         {\r
270                 cl_free( p_srp_session );\r
271                 p_srp_session = NULL;\r
272                 goto exit;\r
273         }\r
274 \r
275         cl_obj_construct( &p_srp_session->obj, SRP_OBJ_TYPE_SESSION );\r
276         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
277                 ("After Construct Session Object ref_cnt = %d\n",\r
278                  p_srp_session->obj.ref_cnt) );\r
279         cl_status = cl_obj_init( &p_srp_session->obj,\r
280                                                          CL_DESTROY_ASYNC,\r
281                                                          __srp_destroying_session,\r
282                                                          __srp_cleanup_session,\r
283                                                          __srp_free_session );\r
284         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
285                 ("After Init Session Object ref_cnt = %d\n",\r
286                 p_srp_session->obj.ref_cnt) );\r
287         if( cl_status != CL_SUCCESS )\r
288         {\r
289                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
290                         ("cl_obj_init returned %s\n", cl_status_text[cl_status]) );\r
291 \r
292                 cl_free( p_srp_session );\r
293                 p_srp_session = NULL;\r
294                 *p_status = IB_ERROR;\r
295                 goto exit;\r
296         }\r
297 \r
298         cl_obj_insert_rel( &p_srp_session->rel,\r
299                                            &p_srp_session->p_hba->obj,\r
300                                            &p_srp_session->obj );\r
301 \r
302         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
303                 ("After Insert Rel Session Object ref_cnt = %d\n",\r
304                 p_srp_session->obj.ref_cnt) );\r
305 \r
306 exit:\r
307         SRP_EXIT( SRP_DBG_PNP );\r
308 \r
309         return ( p_srp_session );\r
310 }\r
311 \r
312 /* srp_new_session */\r
313 /*!\r
314 Orchestrates the connection process for a session to a target\r
315 \r
316 @param p_srp_session - pointer to the session to connect to the target\r
317 \r
318 @return - result of operation\r
319 */\r
320 ib_api_status_t\r
321 srp_session_login(\r
322         IN  srp_session_t   *p_srp_session )\r
323 {\r
324         ib_api_status_t status;\r
325 \r
326         SRP_ENTER( SRP_DBG_PNP );\r
327 \r
328         status = srp_init_hca( &p_srp_session->hca, p_srp_session->p_hba );\r
329         if ( status != IB_SUCCESS )\r
330         {\r
331                 goto exit;\r
332         }\r
333 \r
334         status = srp_open_ca_by_port_gid( &p_srp_session->hca,\r
335                                                                           p_srp_session->p_hba->h_al,\r
336                                                                           &p_srp_session->p_hba->p_srp_path_record->path_rec.sgid,\r
337                                                                           p_srp_session );\r
338         if ( status != IB_SUCCESS )\r
339                 goto exit;\r
340 \r
341         status = srp_connect( &p_srp_session->connection,\r
342                                                   &p_srp_session->hca,\r
343                                                   1, /* initiator_extension */\r
344                                                   (uint8_t)p_srp_session->p_hba->ioc_info.profile.send_msg_depth,\r
345                                                   p_srp_session );\r
346 \r
347 exit:\r
348         SRP_EXIT( SRP_DBG_PNP );\r
349         return ( status );\r
350 }\r