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