[SRP] Handle both SRP I/O Classes, 0xFF from SRP spec r10, and
[mirror/winof/.git] / ulp / srp / kernel / srp_hba.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 \r
34 \r
35 #include "srp_hba.h"\r
36 #include "srp_data.h"\r
37 #include "srp_data_path.h"\r
38 #include "srp_debug.h"\r
39 #if defined(EVENT_TRACING)\r
40 #ifdef offsetof\r
41 #undef offsetof\r
42 #endif\r
43 #include "srp_hba.tmh"\r
44 #endif\r
45 #include "srp_session.h"\r
46 \r
47 #include <complib/cl_byteswap.h>\r
48 #include <complib/cl_bus_ifc.h>\r
49 #include <initguid.h>\r
50 #include <iba/ioc_ifc.h>\r
51 \r
52 \r
53 static void\r
54 __srp_destroying_hba(\r
55         IN                              cl_obj_t                                        *p_obj );\r
56 \r
57 static void\r
58 __srp_cleanup_hba(\r
59         IN                              cl_obj_t                                        *p_obj );\r
60 \r
61 static void\r
62 __srp_free_hba(\r
63         IN                              cl_obj_t                                        *p_obj );\r
64 \r
65 static ib_api_status_t\r
66 __srp_pnp_cb(\r
67         IN                              ib_pnp_rec_t                            *p_pnp_rec );\r
68 \r
69 void\r
70 __srp_dump_ioc_info( const ib_ioc_info_t *p_ioc_info )\r
71 {\r
72         UNUSED_PARAM( p_ioc_info );\r
73 \r
74         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
75                 ("Dumping IOC Info\n") );\r
76 \r
77         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
78                 ("   chassis_guid    = 0x%I64x\n",\r
79                 cl_ntoh64( p_ioc_info->chassis_guid )) );\r
80         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
81                 ("   chassis_slot    = %d\n",\r
82                 p_ioc_info->chassis_slot) );\r
83         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
84                 ("   iou_guid        = 0x%I64x\n",\r
85                 cl_ntoh64( p_ioc_info->iou_guid )) );\r
86         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
87                 ("   iou_slot        = %d\n",\r
88                 p_ioc_info->iou_slot) );\r
89         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG, ("\n") );\r
90         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
91                 ("Dumping IOC Info Profile\n") );\r
92 \r
93         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
94                 ("   ioc_guid        = 0x%I64x\n",\r
95                 cl_ntoh64( p_ioc_info->profile.ioc_guid )) );\r
96         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
97                 ("   vend_id         = %d\n",\r
98                 cl_ntoh32( p_ioc_info->profile.vend_id )) );\r
99         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
100                 ("   dev_id          = %d\n",\r
101                 cl_ntoh32( p_ioc_info->profile.dev_id )) );\r
102         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
103                 ("   dev_ver         = %d\n",\r
104                 cl_ntoh16( p_ioc_info->profile.dev_ver )) );\r
105 \r
106         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
107                 ("   subsys_vend_id  = %d\n",\r
108                 cl_ntoh32( p_ioc_info->profile.subsys_vend_id )) );\r
109         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
110                 ("   subsys_id       = %d\n",\r
111                 cl_ntoh32( p_ioc_info->profile.subsys_id )) );\r
112 \r
113         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
114                 ("   io_class        = %d\n",\r
115                 cl_ntoh16( p_ioc_info->profile.io_class )) );\r
116         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
117                 ("   io_subclass     = %d\n",\r
118                 cl_ntoh16( p_ioc_info->profile.io_subclass )) );\r
119         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
120                 ("   protocol        = %d\n",\r
121                 cl_ntoh16( p_ioc_info->profile.protocol )) );\r
122         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
123                 ("   protocol_ver    = %d\n",\r
124                 cl_ntoh16( p_ioc_info->profile.protocol_ver )) );\r
125 \r
126         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
127                 ("   send_msg_depth  = %d\n",\r
128                 cl_ntoh16( p_ioc_info->profile.send_msg_depth )) );\r
129         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
130                 ("   rdma_read_depth = %d\n",\r
131                 p_ioc_info->profile.rdma_read_depth) );\r
132         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
133                 ("   send_msg_size   = %d\n",\r
134                 cl_ntoh32( p_ioc_info->profile.send_msg_size )) );\r
135         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
136                 ("   rdma_size       = %d\n",\r
137                 cl_ntoh32( p_ioc_info->profile.rdma_size )) );\r
138 \r
139         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
140                 ("   ctrl_ops_cap    = 0x%X\n",\r
141                 p_ioc_info->profile.ctrl_ops_cap) );\r
142         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
143                 ("   num_svc_entries = 0x%X\n",\r
144                 p_ioc_info->profile.num_svc_entries) );\r
145         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
146                 ("   id_string       = %s\n",\r
147                 p_ioc_info->profile.id_string) );\r
148 }\r
149 \r
150 \r
151 static boolean_t\r
152 __get_ioc_ifc(\r
153         IN                              srp_hba_t* const                        p_hba )\r
154 {\r
155         NTSTATUS                        status;\r
156         ib_al_ifc_data_t        data;\r
157         IO_STACK_LOCATION       io_stack;\r
158 \r
159         SRP_ENTER( SRP_DBG_PNP );\r
160 \r
161         /* Query for our interface. */\r
162         data.size = sizeof(ioc_ifc_data_t);\r
163         data.version = IOC_INTERFACE_DATA_VERSION;\r
164         data.type = &GUID_IOC_INTERFACE_DATA;\r
165         data.p_data = &p_hba->info;\r
166 \r
167         io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
168         io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
169         io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
170         io_stack.Parameters.QueryInterface.Interface = (INTERFACE*)&p_hba->ifc;\r
171         io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
172         io_stack.Parameters.QueryInterface.InterfaceType = &GUID_IB_AL_INTERFACE;\r
173 \r
174         status = cl_fwd_query_ifc( gp_self_do, &io_stack );\r
175         if( !NT_SUCCESS( status ) )\r
176         {\r
177                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
178                         ("Query interface for IOU parameters returned %08x.\n", status) );\r
179                 return FALSE;\r
180         }\r
181         else\r
182         {\r
183                 /*\r
184                  * Dereference the interface now so that the bus driver doesn't fail a\r
185                  * query remove IRP.  We will always get unloaded before the bus driver\r
186                  * since we're a child device.\r
187                  */\r
188                 p_hba->ifc.wdm.InterfaceDereference( p_hba->ifc.wdm.Context );\r
189                 SRP_EXIT( SRP_DBG_PNP );\r
190                 return TRUE;\r
191         }\r
192 }\r
193 \r
194 \r
195 ib_api_status_t\r
196 srp_hba_create(\r
197         IN                              cl_obj_t* const                         p_drv_obj,\r
198                 OUT                     srp_ext_t* const                        p_ext )\r
199 {\r
200         srp_hba_t                       *p_hba;\r
201         cl_status_t                     cl_status;\r
202         ib_api_status_t         ib_status;\r
203         ib_pnp_req_t            pnp_req;\r
204         uint32_t                        i;\r
205 \r
206         SRP_ENTER( SRP_DBG_PNP );\r
207 \r
208         p_hba = (srp_hba_t*)cl_zalloc( sizeof(srp_hba_t) );\r
209         if( !p_hba )\r
210         {\r
211                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
212                         ("Failed to allocate srp_hba_t structure.\n") );\r
213                 return IB_INSUFFICIENT_MEMORY;\r
214         }\r
215 \r
216         cl_qlist_init( &p_hba->path_record_list );\r
217         cl_spinlock_init( &p_hba->path_record_list_lock );\r
218 \r
219         /* Store instance parameters. */\r
220         p_hba->p_ext = p_ext;\r
221         p_hba->max_sg = 0xFFFFFFFF;\r
222         p_hba->max_srb_ext_sz = 0xFFFFFFFF;\r
223 \r
224         if( !__get_ioc_ifc( p_hba ) )\r
225         {\r
226                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
227                         ("__get_ioc_ifc failed.\n") );\r
228                 return IB_ERROR;\r
229         }\r
230 \r
231         for ( i = 0; i < SRP_MAX_SERVICE_ENTRIES; i++ )\r
232         {\r
233                 p_hba->session_list[i] = NULL;\r
234         }\r
235 \r
236         cl_obj_construct( &p_hba->obj, SRP_OBJ_TYPE_HBA );\r
237         cl_status = cl_obj_init( &p_hba->obj, CL_DESTROY_ASYNC,\r
238                 __srp_destroying_hba, __srp_cleanup_hba, __srp_free_hba );\r
239         if( cl_status != CL_SUCCESS )\r
240         {\r
241                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
242                         ("cl_obj_init returned %s\n", cl_status_text[cl_status]) );\r
243                 return IB_ERROR;\r
244         }\r
245 \r
246         ib_status = p_hba->ifc.open_al( &p_hba->h_al );\r
247         if( ib_status != IB_SUCCESS )\r
248         {\r
249                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
250                         ("ib_open_al returned %s\n", p_hba->ifc.get_err_str( ib_status )) );\r
251                 goto err;\r
252         }\r
253 \r
254         /* Register for IOC events */\r
255         pnp_req.pfn_pnp_cb = __srp_pnp_cb;\r
256         pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC;\r
257         pnp_req.pnp_context = p_hba;\r
258         /* Reference the HBA object before registering for PnP notifications. */\r
259         cl_obj_ref( &p_hba->obj );\r
260 \r
261         cl_obj_insert_rel( &p_hba->rel, p_drv_obj, &p_hba->obj );\r
262 \r
263         ib_status = p_hba->ifc.reg_pnp( p_hba->h_al, &pnp_req, &p_hba->h_pnp );\r
264         if( ib_status != IB_SUCCESS )\r
265         {\r
266                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
267                         ("ib_reg_pnp returned %s\n", p_hba->ifc.get_err_str( ib_status )) );\r
268                 goto err;\r
269         }\r
270         ib_status = IB_ERROR;\r
271         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
272         {\r
273                 if ( p_hba->session_list[i] != NULL )\r
274                         ib_status = IB_SUCCESS;\r
275         }\r
276         \r
277         if( ib_status != IB_SUCCESS )\r
278         {\r
279                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
280                         ("Session Connection Failure.\n") );\r
281 \r
282 err:\r
283                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
284                         ("HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
285                 cl_obj_destroy( &p_hba->obj );\r
286 \r
287                 return ib_status;\r
288         }\r
289 \r
290         /*\r
291          * Add the HBA to the driver object's child list.  This will cause\r
292          * everything to clean up properly in case we miss an unload notification.\r
293          */\r
294         p_ext->p_hba = p_hba;\r
295 \r
296         SRP_EXIT( SRP_DBG_PNP );\r
297         return ib_status;\r
298 }\r
299 \r
300 \r
301 static void\r
302 __srp_destroying_hba(\r
303         IN              cl_obj_t                    *p_obj )\r
304 {\r
305         srp_hba_t       *p_hba;\r
306 \r
307         SRP_ENTER( SRP_DBG_PNP );\r
308 \r
309         p_hba = PARENT_STRUCT( p_obj, srp_hba_t, obj );\r
310 \r
311         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
312                 ("Before dereg pnp HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
313 \r
314         if( p_hba->h_pnp )\r
315         {\r
316                 p_hba->ifc.dereg_pnp( p_hba->h_pnp, cl_obj_deref );\r
317         }\r
318 \r
319         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
320                 ("After dereg pnp HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
321 \r
322         SRP_EXIT( SRP_DBG_PNP );\r
323 }\r
324 \r
325 static void\r
326 __srp_remove_path_records(\r
327         IN              srp_hba_t                   *p_hba )\r
328 {\r
329         srp_path_record_t   *p_srp_path_record;\r
330 \r
331         SRP_ENTER( SRP_DBG_PNP );\r
332 \r
333         cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
334         p_srp_path_record = (srp_path_record_t *)cl_qlist_remove_head( &p_hba->path_record_list );\r
335 \r
336         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
337                 ("Removing any remaining path records.\n") );\r
338 \r
339         while ( p_srp_path_record != (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
340         {\r
341                 cl_free( p_srp_path_record );\r
342                 p_srp_path_record = (srp_path_record_t *)cl_qlist_remove_head( &p_hba->path_record_list );\r
343         }\r
344 \r
345         cl_spinlock_release( &p_hba->path_record_list_lock );\r
346 \r
347         SRP_EXIT( SRP_DBG_PNP );\r
348 }\r
349 \r
350 static void\r
351 __srp_cleanup_hba(\r
352         IN              cl_obj_t                    *p_obj )\r
353 {\r
354         srp_hba_t   *p_hba;\r
355 \r
356         SRP_ENTER( SRP_DBG_PNP );\r
357 \r
358         p_hba = PARENT_STRUCT( p_obj, srp_hba_t, obj );\r
359 \r
360         if( p_hba->h_al )\r
361                 p_hba->ifc.close_al( p_hba->h_al );\r
362 \r
363         __srp_remove_path_records( p_hba );\r
364 \r
365         cl_spinlock_destroy( &p_hba->path_record_list_lock );\r
366 \r
367         if ( p_hba->p_svc_entries )\r
368                 cl_free( p_hba->p_svc_entries );\r
369 \r
370         SRP_EXIT( SRP_DBG_PNP );\r
371 }\r
372 \r
373 \r
374 static void\r
375 __srp_free_hba(\r
376         IN              cl_obj_t                    *p_obj )\r
377 {\r
378         srp_hba_t       *p_hba;\r
379 \r
380         SRP_ENTER( SRP_DBG_PNP );\r
381 \r
382         p_hba = PARENT_STRUCT( p_obj, srp_hba_t, obj );\r
383 \r
384         cl_obj_deinit( p_obj );\r
385         cl_free( p_hba );\r
386 \r
387         SRP_EXIT( SRP_DBG_PNP );\r
388 }\r
389 \r
390 static BOOLEAN\r
391 __srp_validate_ioc(\r
392         IN  ib_pnp_ioc_rec_t    *p_ioc_rec )\r
393 {\r
394         SRP_ENTER( SRP_DBG_PNP );\r
395 \r
396         // Is this really an SRP device?\r
397         if ( ( cl_ntoh16( p_ioc_rec->info.profile.io_class )  != SRP_IO_CLASS &&\r
398                    cl_ntoh16( p_ioc_rec->info.profile.io_class )  != SRP_IO_CLASS_R10 ) ||\r
399                  cl_ntoh16( p_ioc_rec->info.profile.io_subclass ) != SRP_IO_SUBCLASS )\r
400         {\r
401                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
402                                                 ("Not an SRP CLASS(0x%x)/SUBCLASS(0x%x).\n",\r
403                                                 cl_ntoh16( p_ioc_rec->info.profile.io_class ),\r
404                                                 cl_ntoh16( p_ioc_rec->info.profile.io_subclass )) );\r
405                 return FALSE;\r
406         }\r
407 \r
408         // Does it have the required features?\r
409         if ( cl_ntoh16( p_ioc_rec->info.profile.protocol )     != SRP_PROTOCOL     ||\r
410                  cl_ntoh16( p_ioc_rec->info.profile.protocol_ver ) != SRP_PROTOCOL_VER ||\r
411                  !(p_ioc_rec->info.profile.ctrl_ops_cap & CTRL_OPS_CAP_ST) ||\r
412                  !(p_ioc_rec->info.profile.ctrl_ops_cap & CTRL_OPS_CAP_SF) ||\r
413                  !(p_ioc_rec->info.profile.ctrl_ops_cap & CTRL_OPS_CAP_RF) ||\r
414                  !(p_ioc_rec->info.profile.ctrl_ops_cap & CTRL_OPS_CAP_WF) )\r
415         {\r
416                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
417                         ("Not an SRP PROTOCOL/PROTOCOL_VER.\n") );\r
418                 return FALSE;\r
419         }\r
420 \r
421         // Can it handle our IO requirements?\r
422         if ( cl_ntoh32( p_ioc_rec->info.profile.send_msg_size )  <  SRP_MIN_TGT_TO_INI_IU ||\r
423                  cl_ntoh16( p_ioc_rec->info.profile.send_msg_depth ) == 0 ||\r
424                  cl_ntoh32( p_ioc_rec->info.profile.rdma_size )      <  SRP_MIN_TGT_TO_INI_DMA )\r
425         {\r
426                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
427                         ("Device Not Capable.\n") );\r
428                 return FALSE;\r
429         }\r
430 \r
431         SRP_EXIT( SRP_DBG_PNP );\r
432 \r
433         return TRUE;\r
434 }\r
435 \r
436 static BOOLEAN\r
437 __srp_path_rec_equal(\r
438         IN      const ib_path_rec_t     *p_path_rec_1,\r
439         IN      const ib_path_rec_t     *p_path_rec_2,\r
440         IN      BOOLEAN                         check_num_path,\r
441         IN      BOOLEAN                         check_preference )\r
442 {\r
443         SRP_ENTER( SRP_DBG_PNP );\r
444 \r
445         if ( p_path_rec_1->dgid.unicast.prefix != p_path_rec_2->dgid.unicast.prefix )\r
446                 return ( FALSE );\r
447 \r
448         if ( p_path_rec_1->dgid.unicast.interface_id != p_path_rec_2->dgid.unicast.interface_id )\r
449                 return ( FALSE );\r
450 \r
451         if ( p_path_rec_1->sgid.unicast.prefix != p_path_rec_2->sgid.unicast.prefix )\r
452                 return ( FALSE );\r
453 \r
454         if ( p_path_rec_1->sgid.unicast.interface_id != p_path_rec_2->sgid.unicast.interface_id )\r
455                 return ( FALSE );\r
456 \r
457         if ( p_path_rec_1->dlid != p_path_rec_2->dlid )\r
458                 return ( FALSE );\r
459 \r
460         if ( p_path_rec_1->slid != p_path_rec_2->slid )\r
461                 return ( FALSE );\r
462 \r
463         if ( p_path_rec_1->hop_flow_raw.val != p_path_rec_2->hop_flow_raw.val )\r
464         {\r
465                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
466                         ("hop_flow_raw.val does not match.\n") );\r
467                 return ( FALSE );\r
468         }\r
469 \r
470         if ( p_path_rec_1->tclass != p_path_rec_2->tclass )\r
471         {\r
472                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
473                         ("tclass does not match.\n") );\r
474                 return ( FALSE );\r
475         }\r
476 \r
477         if ( p_path_rec_1->num_path != p_path_rec_2->num_path )\r
478         {\r
479                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
480                         ("num_path does not match.\n") );\r
481                 if ( check_num_path == TRUE )\r
482                 {\r
483                         return ( FALSE );\r
484                 }\r
485         }\r
486 \r
487         if ( p_path_rec_1->pkey != p_path_rec_2->pkey )\r
488         {\r
489                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
490                         ("pkey does not match.\n") );\r
491                 return ( FALSE );\r
492         }\r
493 \r
494         if ( p_path_rec_1->sl != p_path_rec_2->sl )\r
495         {\r
496                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
497                         ("sl does not match.\n") );\r
498                 return ( FALSE );\r
499         }\r
500 \r
501         if ( p_path_rec_1->mtu != p_path_rec_2->mtu )\r
502         {\r
503                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
504                         ("mtu does not match.\n") );\r
505                 return ( FALSE );\r
506         }\r
507 \r
508         if ( p_path_rec_1->rate != p_path_rec_2->rate )\r
509         {\r
510                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
511                         ("rate does not match.\n") );\r
512                 return ( FALSE );\r
513         }\r
514 \r
515         if ( p_path_rec_1->pkt_life != p_path_rec_2->pkt_life )\r
516         {\r
517                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
518                         ("pkt_life does not match.\n") );\r
519                 return ( FALSE );\r
520         }\r
521 \r
522         if ( p_path_rec_1->preference != p_path_rec_2->preference )\r
523         {\r
524                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
525                         ("preference does not match.\n") );\r
526                 if ( check_preference == TRUE )\r
527                 {\r
528                         return ( FALSE );\r
529                 }\r
530         }\r
531 \r
532 #if defined( _DEBUG_ )\r
533 \r
534         if ( p_path_rec_1->resv0 != p_path_rec_2->resv0 )\r
535         {\r
536                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
537                         ("resv0 does not match.\n") );\r
538         }\r
539 \r
540         if ( p_path_rec_1->resv1 != p_path_rec_2->resv1 )\r
541         {\r
542                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
543                         ("resv1 does not match.\n") );\r
544         }\r
545 \r
546         if ( p_path_rec_1->resv2 != p_path_rec_2->resv2 )\r
547         {\r
548                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
549                         ("resv2 does not match.\n") );\r
550         }\r
551 \r
552         if ( cl_memcmp( p_path_rec_1, p_path_rec_2, sizeof( ib_path_rec_t ) ) != 0 )\r
553         {\r
554                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
555                         ("p_path_rec_1 does not match p_path_rec_2.\n") );\r
556         }\r
557         else\r
558         {\r
559                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
560                         ("p_path_rec_1 matches p_path_rec_2.\n") );\r
561         }\r
562 \r
563 #endif\r
564 \r
565         SRP_EXIT( SRP_DBG_PNP );\r
566 \r
567         return ( TRUE );\r
568 }\r
569 \r
570 static\r
571 srp_path_record_t*\r
572 __srp_find_path(\r
573         IN  srp_hba_t               *p_hba,\r
574         IN  const ib_path_rec_t     *p_path_rec,\r
575         IN  BOOLEAN                 check_num_path,\r
576         IN  BOOLEAN                 check_preference )\r
577 {\r
578         srp_path_record_t   *p_srp_path_record;\r
579 \r
580         SRP_ENTER( SRP_DBG_PNP );\r
581 \r
582         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
583                 ("Finding path record (slid:%d dlid:%d) for %s.\n",\r
584                 p_path_rec->slid,\r
585                 p_path_rec->dlid,\r
586                 p_hba->ioc_info.profile.id_string) );\r
587 \r
588         cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
589 \r
590         p_srp_path_record = (srp_path_record_t *)cl_qlist_head( &p_hba->path_record_list );\r
591 \r
592         while ( p_srp_path_record != (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
593         {\r
594                 if ( __srp_path_rec_equal( (const ib_path_rec_t *)&p_srp_path_record->path_rec,\r
595                                                                         p_path_rec,\r
596                                                                         check_num_path,\r
597                                                                         check_preference ) == TRUE )\r
598                 {\r
599                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
600                                 ("Found path record (slid:%d dlid:%d) for %s.\n",\r
601                                 p_path_rec->slid,\r
602                                 p_path_rec->dlid,\r
603                                 p_hba->ioc_info.profile.id_string) );\r
604                         break;\r
605                 }\r
606 \r
607                 p_srp_path_record = (srp_path_record_t *)cl_qlist_next( &p_srp_path_record->list_item );\r
608         }\r
609 \r
610         if ( p_srp_path_record == (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
611         {\r
612                 p_srp_path_record = NULL;\r
613         }\r
614 \r
615         cl_spinlock_release( &p_hba->path_record_list_lock );\r
616 \r
617         SRP_EXIT( SRP_DBG_PNP );\r
618 \r
619         return p_srp_path_record;\r
620 }\r
621 \r
622 static\r
623 srp_path_record_t*\r
624 __srp_remove_path(\r
625         IN  srp_hba_t               *p_hba,\r
626         IN  const ib_path_rec_t     *p_path_rec )\r
627 {\r
628         srp_path_record_t   *p_srp_path_record;\r
629 \r
630         SRP_ENTER( SRP_DBG_PNP );\r
631 \r
632         p_srp_path_record = __srp_find_path( p_hba, p_path_rec, TRUE, TRUE );\r
633         if ( p_srp_path_record != NULL )\r
634         {\r
635                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
636 \r
637                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
638                         ("Removing path record (slid:%d dlid:%d) for %s.\n",\r
639                         p_path_rec->slid,\r
640                         p_path_rec->dlid,\r
641                         p_hba->ioc_info.profile.id_string) );\r
642 \r
643                 cl_qlist_remove_item( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
644 \r
645                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
646         }\r
647 \r
648         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
649                 ("Current Path count for %s = %d \n",\r
650                  p_hba->ioc_info.profile.id_string,\r
651                  (int)cl_qlist_count( &p_hba->path_record_list )) );\r
652 \r
653         SRP_EXIT( SRP_DBG_PNP );\r
654 \r
655         return p_srp_path_record;\r
656 }\r
657 \r
658 static\r
659 srp_path_record_t*\r
660 __srp_add_path(\r
661         IN  srp_hba_t               *p_hba,\r
662         IN  const ib_path_rec_t     *p_path_rec )\r
663 {\r
664         srp_path_record_t   *p_srp_path_record;\r
665 \r
666         SRP_ENTER( SRP_DBG_PNP );\r
667 \r
668         p_srp_path_record = __srp_find_path( p_hba, p_path_rec, FALSE, FALSE );\r
669         if ( p_srp_path_record != NULL )\r
670         {\r
671                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
672                 p_srp_path_record->path_rec = *p_path_rec;\r
673                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
674 \r
675                 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DEBUG,\r
676                         ("Discarding/Updating duplicate path record (slid:%d dlid:%d) for %s.\n",\r
677                         p_path_rec->slid,\r
678                         p_path_rec->dlid,\r
679                         p_hba->ioc_info.profile.id_string) );\r
680 \r
681                 goto exit;\r
682         }\r
683 \r
684         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
685                 ("Adding path record (slid:%d dlid:%d) for %s.\n",\r
686                 p_path_rec->slid,\r
687                 p_path_rec->dlid,\r
688                 p_hba->ioc_info.profile.id_string) );\r
689 \r
690 \r
691         p_srp_path_record = cl_zalloc( sizeof( srp_path_record_t ) );\r
692         if ( p_srp_path_record == NULL )\r
693         {\r
694                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
695                         ("Insufficient Memory.\n") );\r
696         }\r
697         else\r
698         {\r
699                 p_srp_path_record->path_rec = *p_path_rec;\r
700 \r
701                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
702                 cl_qlist_insert_tail( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
703                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
704         }\r
705 \r
706         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
707                 ("Current Path count for %s = %d \n",\r
708                  p_hba->ioc_info.profile.id_string,\r
709                  (int)cl_qlist_count( &p_hba->path_record_list )) );\r
710 \r
711 exit:\r
712         SRP_EXIT( SRP_DBG_PNP );\r
713 \r
714         return p_srp_path_record;\r
715 }\r
716 \r
717 static ib_api_status_t\r
718 __srp_connect_sessions(\r
719         IN OUT srp_hba_t    *p_hba )\r
720 {\r
721         uint32_t        i;\r
722         srp_session_t   *p_session;\r
723         ib_api_status_t status = IB_ERROR;\r
724         BOOLEAN any_ioc_connected = FALSE;\r
725 \r
726         SRP_ENTER( SRP_DBG_PNP );\r
727 \r
728         /* Create the session(s). */\r
729         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
730         {\r
731                 int     retry_count = 0;\r
732 \r
733                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
734                         ("Creating New Session For Service Entry Index %d.\n",\r
735                         p_hba->ioc_info.profile.num_svc_entries));\r
736 \r
737                 p_session = srp_new_session(\r
738                         p_hba, &p_hba->p_svc_entries[i], &status );\r
739                 if( p_session == NULL )\r
740                 {\r
741                         status = IB_INSUFFICIENT_MEMORY;\r
742                         continue;\r
743                 }\r
744 \r
745                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
746                         ("New Session For Service Entry Index %d Created.\n",\r
747                         p_hba->ioc_info.profile.num_svc_entries));\r
748 \r
749                 do\r
750                 {\r
751                         retry_count++;\r
752 \r
753                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
754                                 ("Attempting to connect %s. Connection Attempt Count = %d.\n",\r
755                                  p_hba->ioc_info.profile.id_string,\r
756                                  retry_count) );\r
757                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
758                                 ("Logging Into Session.\n"));\r
759                         status = srp_session_login( p_session );\r
760                         if ( status == IB_SUCCESS )\r
761                         {\r
762                                 any_ioc_connected = TRUE;\r
763 \r
764                                 if ( (p_hba->max_sg >\r
765                                         p_session->connection.max_scatter_gather_entries)\r
766                                         && !(p_session->connection.descriptor_format &\r
767                                         DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS) )\r
768                                 {\r
769                                         p_hba->max_sg = p_session->connection.max_scatter_gather_entries;\r
770                                 }\r
771 \r
772                                 if ( p_hba->max_srb_ext_sz > p_session->connection.init_to_targ_iu_sz )\r
773                                 {\r
774                                         p_hba->max_srb_ext_sz =\r
775                                                 sizeof( srp_send_descriptor_t ) -\r
776                                                 SRP_MIN_IU_SIZE +\r
777                                                 p_session->connection.init_to_targ_iu_sz;\r
778                                 }\r
779 \r
780                                 cl_obj_lock( &p_hba->obj );\r
781                                 p_hba->session_list[i] = p_session;\r
782                                 cl_obj_unlock( &p_hba->obj );\r
783 \r
784                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
785                                         ("Session Login Issued Successfully.\n"));\r
786                         }\r
787                         else\r
788                         {\r
789                                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
790                                         ("Session Login Failure Status = %d.\n", status));\r
791                         }\r
792                 } while ( (status != IB_SUCCESS) && (retry_count < 3) );\r
793 \r
794                 if( status != IB_SUCCESS )\r
795                 {\r
796                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
797                                 ("Session Object ref_cnt = %d\n", p_session->obj.ref_cnt) );\r
798                         cl_obj_destroy( &p_session->obj );\r
799                 }\r
800         }\r
801 \r
802         if ( any_ioc_connected == TRUE )\r
803         {\r
804                 status = IB_SUCCESS;\r
805                 if ( p_hba->adapter_paused == TRUE )\r
806                 {\r
807                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
808                                 ("Resuming Adapter for %s.\n",\r
809                                 p_hba->ioc_info.profile.id_string) );\r
810                         p_hba->adapter_paused = FALSE;\r
811                         StorPortReady( p_hba->p_ext );\r
812                         //StorPortNotification( BusChangeDetected, p_hba->p_ext, 0 );\r
813                 }\r
814         }\r
815 \r
816         SRP_EXIT( SRP_DBG_PNP );\r
817 \r
818         return status;\r
819 }\r
820 \r
821 static void\r
822 __srp_disconnect_sessions(\r
823         IN                              srp_hba_t                                       *p_hba,\r
824         IN                              BOOLEAN                                         pause_adapter )\r
825 {\r
826         uint32_t                i;\r
827         srp_session_t   *p_session;\r
828 \r
829         SRP_ENTER( SRP_DBG_PNP );\r
830 \r
831         cl_obj_lock( &p_hba->obj );\r
832 \r
833         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
834         {\r
835                 if ( p_hba->session_list[i] != NULL )\r
836                 {\r
837                         break;\r
838                 }\r
839         }\r
840 \r
841         cl_obj_unlock( &p_hba->obj );\r
842 \r
843         if ( i == p_hba->ioc_info.profile.num_svc_entries )\r
844         {\r
845                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
846                         ("No current connections to %s.\n",\r
847                         p_hba->ioc_info.profile.id_string) );\r
848                 goto exit;\r
849         }\r
850 \r
851         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
852                 ("Current path to %s has been lost.\n",\r
853                 p_hba->ioc_info.profile.id_string) );\r
854 \r
855         p_hba->p_srp_path_record = NULL;\r
856 \r
857         if ( pause_adapter == TRUE )\r
858         {\r
859                 if ( p_hba->adapter_paused == FALSE )\r
860                 {\r
861                         p_hba->adapter_paused = TRUE;\r
862                         StorPortBusy( p_hba->p_ext, (ULONG)-1 );\r
863                         StorPortCompleteRequest( p_hba->p_ext,\r
864                                                                          SP_UNTAGGED,\r
865                                                                          SP_UNTAGGED,\r
866                                                                          SP_UNTAGGED,\r
867                                                                          SRB_STATUS_BUSY );\r
868                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
869                                 ("Pausing Adapter for %s.\n",\r
870                                 p_hba->ioc_info.profile.id_string) );\r
871                 }\r
872         }\r
873 \r
874         /* Destroy all the connections. */\r
875         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
876                 ("Destroy all connections to %s.\n",\r
877                 p_hba->ioc_info.profile.id_string) );\r
878 \r
879         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
880         {\r
881                 cl_obj_lock( &p_hba->obj );\r
882                 p_session = p_hba->session_list[i];\r
883                 p_hba->session_list[i] = NULL;\r
884                 cl_obj_unlock( &p_hba->obj );\r
885 \r
886                 if ( p_session != NULL )\r
887                 {\r
888                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
889                                 ("Session Object ref_cnt = %d\n", p_session->obj.ref_cnt) );\r
890                         __srp_cleanup_session ( &p_session->obj );\r
891                         cl_obj_destroy( &p_session->obj );\r
892                 }\r
893                 else\r
894                 {\r
895                         SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DEBUG,\r
896                                 ("Session for Target ID %d on %s is NULL.\n",\r
897                                  i,\r
898                                  p_hba->ioc_info.profile.id_string) ); // <-- OK in a shutdown or target disconnect\r
899                 }\r
900         }\r
901 \r
902 exit:\r
903         SRP_EXIT( SRP_DBG_PNP );\r
904 }\r
905 \r
906 static ib_api_status_t\r
907 __srp_connect_path(\r
908         IN  srp_hba_t   *p_hba )\r
909 {\r
910         ib_api_status_t     status = IB_ERROR;\r
911         srp_path_record_t   *p_srp_path_record;\r
912 \r
913         SRP_ENTER( SRP_DBG_PNP );\r
914 \r
915         while ( g_srp_system_shutdown == FALSE )\r
916         {\r
917                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
918                         ("Searching for path to %s.\n",\r
919                          p_hba->ioc_info.profile.id_string) );\r
920 \r
921                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
922                 p_srp_path_record = (srp_path_record_t *)cl_qlist_head( &p_hba->path_record_list );\r
923                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
924                 if ( p_srp_path_record == (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
925                 {\r
926                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
927                                 ("No paths to %s found.\n",\r
928                                 p_hba->ioc_info.profile.id_string) );\r
929                         break;\r
930                 }\r
931 \r
932                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
933                         ("Connecting path to %s.\n",\r
934                         p_hba->ioc_info.profile.id_string) );\r
935 \r
936                 p_hba->p_srp_path_record = p_srp_path_record;\r
937                 status = __srp_connect_sessions( p_hba );\r
938                 if ( status == IB_SUCCESS )\r
939                 {\r
940                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
941                                 ("Path to %s has connected.\n",\r
942                                 p_hba->ioc_info.profile.id_string) );\r
943                         break;\r
944                 }\r
945 \r
946                 p_hba->p_srp_path_record = NULL;\r
947                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
948                 cl_qlist_remove_item( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
949                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
950                 cl_free( p_srp_path_record );\r
951         }\r
952 \r
953         SRP_EXIT( SRP_DBG_PNP );\r
954 \r
955         return status;\r
956 }\r
957 \r
958 static ib_api_status_t\r
959 __srp_pnp_cb(\r
960         IN              ib_pnp_rec_t                *p_pnp_rec )\r
961 {\r
962         ib_api_status_t                 status = IB_SUCCESS;\r
963         ib_pnp_ioc_rec_t                *p_ioc_rec;\r
964         ib_pnp_ioc_path_rec_t   *p_ioc_path;\r
965         srp_hba_t                               *p_hba;\r
966         srp_path_record_t               *p_srp_path_record;\r
967         \r
968         SRP_ENTER( SRP_DBG_PNP );\r
969 \r
970         p_hba = (srp_hba_t* __ptr64)p_pnp_rec->pnp_context;\r
971         p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
972         p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
973 \r
974         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
975                 ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
976                 p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
977 \r
978 \r
979         switch( p_pnp_rec->pnp_event )\r
980         {\r
981                 case IB_PNP_IOC_ADD:\r
982                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
983                                 ("IB_PNP_IOC_ADD for %s.\n",\r
984                                 p_ioc_rec->info.profile.id_string) );\r
985 \r
986                         __srp_dump_ioc_info( &p_ioc_rec->info );\r
987 \r
988                         /*\r
989                          * Trap our CA GUID so we filter path notifications\r
990                          * for our bound CA only.\r
991                          */\r
992                         if( p_ioc_rec->ca_guid != p_hba->info.ca_guid )\r
993                         {\r
994                                 SRP_PRINT_EXIT( TRACE_LEVEL_WARNING, SRP_DBG_DEBUG,\r
995                                         ("Ignoring CA GUID.\n") );\r
996                                 status = IB_INVALID_GUID;\r
997                                 break;\r
998                         }\r
999 \r
1000                         /* Trap our IOC GUID so we can get path notification events. */\r
1001                         if( p_ioc_rec->info.profile.ioc_guid != p_hba->info.guid )\r
1002                         {\r
1003                                 SRP_PRINT_EXIT( TRACE_LEVEL_WARNING, SRP_DBG_DEBUG,\r
1004                                         ("Ignoring GUID.\n") );\r
1005                                 status = IB_INVALID_GUID;\r
1006                                 break;\r
1007                         }\r
1008 \r
1009                         if ( __srp_validate_ioc( p_ioc_rec ) == FALSE )\r
1010                         {\r
1011                                 status = IB_INVALID_GUID;\r
1012                                 break;\r
1013                         }\r
1014 \r
1015                         p_hba->ioc_info = p_ioc_rec->info;\r
1016                         p_hba->p_svc_entries = cl_zalloc( sizeof(ib_svc_entry_t) * p_hba->ioc_info.profile.num_svc_entries );\r
1017                         if ( p_hba->p_svc_entries == NULL )\r
1018                         {\r
1019                                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
1020                                         ("Insufficient Memory.\n") );\r
1021                                 status = IB_INSUFFICIENT_MEMORY;\r
1022                                 break;\r
1023                         }\r
1024 \r
1025                         cl_memcpy ( p_hba->p_svc_entries,\r
1026                                                 p_ioc_rec->svc_entry_array,\r
1027                                                 sizeof(ib_svc_entry_t) * p_hba->ioc_info.profile.num_svc_entries);\r
1028 \r
1029                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
1030                                 ("Found %d Service Entries.\n",\r
1031                                 p_hba->ioc_info.profile.num_svc_entries));\r
1032                         break;\r
1033 \r
1034                 case IB_PNP_IOC_REMOVE:\r
1035                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
1036                                 ("IB_PNP_IOC_REMOVE for %s.\n",\r
1037                                 p_hba->ioc_info.profile.id_string) );\r
1038 \r
1039                         CL_ASSERT( p_pnp_rec->guid == p_hba->info.guid );\r
1040 \r
1041                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
1042                                 ("Hey!!! Our IOC went away.\n") );\r
1043 \r
1044                         __srp_disconnect_sessions( p_hba, FALSE );\r
1045                         __srp_remove_path_records( p_hba );\r
1046                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
1047                                 ("HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
1048                         break;\r
1049 \r
1050                 case IB_PNP_IOC_PATH_ADD:\r
1051                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
1052                                 ("IB_PNP_IOC_PATH_ADD (slid:%d dlid:%d) for %s.\n",\r
1053                                 p_ioc_path->path.slid,\r
1054                                 p_ioc_path->path.dlid,\r
1055                                 p_hba->ioc_info.profile.id_string));\r
1056 \r
1057                         p_srp_path_record = __srp_add_path( p_hba, &p_ioc_path->path );\r
1058                         if ( p_srp_path_record == NULL )\r
1059                         {\r
1060                                 status = IB_INSUFFICIENT_MEMORY;\r
1061                                 break;\r
1062                         }\r
1063 \r
1064                         if ( p_hba->p_srp_path_record == NULL )\r
1065                         {\r
1066                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
1067                                         ("Connecting new path to %s.\n",\r
1068                                         p_hba->ioc_info.profile.id_string) );\r
1069                                 status = __srp_connect_path( p_hba );\r
1070                         }\r
1071                         break;\r
1072 \r
1073                 case IB_PNP_IOC_PATH_REMOVE:\r
1074                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
1075                                 ("IB_PNP_IOC_PATH_REMOVE (slid:%d dlid:%d) for %s.\n",\r
1076                                 p_ioc_path->path.slid,\r
1077                                 p_ioc_path->path.dlid,\r
1078                                 p_hba->ioc_info.profile.id_string));\r
1079 \r
1080                         p_srp_path_record = __srp_remove_path( p_hba, &p_ioc_path->path );\r
1081                         if ( p_srp_path_record != NULL )\r
1082                         {\r
1083                                 if ( p_srp_path_record == p_hba->p_srp_path_record )\r
1084                                 {\r
1085                                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
1086                                                 ("Current path to %s has been lost.\n",\r
1087                                                  p_hba->ioc_info.profile.id_string) );\r
1088 \r
1089                                         if ( g_srp_system_shutdown == FALSE )\r
1090                                         {\r
1091                                                 __srp_disconnect_sessions( p_hba, TRUE );\r
1092                                                 status = __srp_connect_path( p_hba );\r
1093                                         }\r
1094                                         else\r
1095                                         {\r
1096                                                 __srp_disconnect_sessions( p_hba, FALSE );\r
1097                                         }\r
1098                                 }\r
1099 \r
1100                                 cl_free( p_srp_path_record );\r
1101                         }\r
1102                         break;\r
1103 \r
1104                 default:\r
1105                         CL_ASSERT( p_pnp_rec->pnp_event == IB_PNP_IOC_ADD ||\r
1106                                 p_pnp_rec->pnp_event == IB_PNP_IOC_REMOVE ||\r
1107                                 p_pnp_rec->pnp_event == IB_PNP_IOC_PATH_ADD ||\r
1108                                 p_pnp_rec->pnp_event == IB_PNP_IOC_PATH_REMOVE );\r
1109                         break;\r
1110         }\r
1111 \r
1112         SRP_EXIT( SRP_DBG_PNP );\r
1113         return status;\r
1114 }\r