049b2eab2c0291a89d392d90504e0c6de2d86f29
[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.val != p_path_rec_2->hop_flow_raw.val )\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 ( p_path_rec_1->sl != p_path_rec_2->sl )\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->resv0 != p_path_rec_2->resv0 )\r
536         {\r
537                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
538                         ("resv0 does not match.\n") );\r
539         }\r
540 \r
541         if ( p_path_rec_1->resv1 != p_path_rec_2->resv1 )\r
542         {\r
543                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
544                         ("resv1 does not match.\n") );\r
545         }\r
546 \r
547         if ( p_path_rec_1->resv2 != p_path_rec_2->resv2 )\r
548         {\r
549                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
550                         ("resv2 does not match.\n") );\r
551         }\r
552 \r
553         if ( cl_memcmp( p_path_rec_1, p_path_rec_2, sizeof( ib_path_rec_t ) ) != 0 )\r
554         {\r
555                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
556                         ("p_path_rec_1 does not match p_path_rec_2.\n") );\r
557         }\r
558         else\r
559         {\r
560                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
561                         ("p_path_rec_1 matches p_path_rec_2.\n") );\r
562         }\r
563 \r
564 #endif\r
565 \r
566         SRP_EXIT( SRP_DBG_PNP );\r
567 \r
568         return ( TRUE );\r
569 }\r
570 \r
571 static\r
572 srp_path_record_t*\r
573 __srp_find_path(\r
574         IN  srp_hba_t               *p_hba,\r
575         IN  const ib_path_rec_t     *p_path_rec,\r
576         IN  BOOLEAN                 check_num_path,\r
577         IN  BOOLEAN                 check_preference )\r
578 {\r
579         srp_path_record_t   *p_srp_path_record;\r
580 \r
581         SRP_ENTER( SRP_DBG_PNP );\r
582 \r
583         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
584                 ("Finding path record (slid:0x%x dlid:0x%x) for %s.\n",\r
585                 cl_ntoh16(p_path_rec->slid),\r
586                 cl_ntoh16(p_path_rec->dlid),\r
587                 p_hba->ioc_info.profile.id_string) );\r
588 \r
589         cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
590 \r
591         p_srp_path_record = (srp_path_record_t *)cl_qlist_head( &p_hba->path_record_list );\r
592 \r
593         while ( p_srp_path_record != (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
594         {\r
595                 if ( __srp_path_rec_equal( (const ib_path_rec_t *)&p_srp_path_record->path_rec,\r
596                                                                         p_path_rec,\r
597                                                                         check_num_path,\r
598                                                                         check_preference ) == TRUE )\r
599                 {\r
600                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
601                                 ("Found path record (slid:0x%x dlid:0x%x) for %s.\n",\r
602                                 cl_ntoh16(p_path_rec->slid),\r
603                                 cl_ntoh16(p_path_rec->dlid),\r
604                                 p_hba->ioc_info.profile.id_string) );\r
605                         break;\r
606                 }\r
607 \r
608                 p_srp_path_record = (srp_path_record_t *)cl_qlist_next( &p_srp_path_record->list_item );\r
609         }\r
610 \r
611         if ( p_srp_path_record == (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
612         {\r
613                 p_srp_path_record = NULL;\r
614         }\r
615 \r
616         cl_spinlock_release( &p_hba->path_record_list_lock );\r
617 \r
618         SRP_EXIT( SRP_DBG_PNP );\r
619 \r
620         return p_srp_path_record;\r
621 }\r
622 \r
623 static\r
624 srp_path_record_t*\r
625 __srp_remove_path(\r
626         IN  srp_hba_t               *p_hba,\r
627         IN  const ib_path_rec_t     *p_path_rec )\r
628 {\r
629         srp_path_record_t   *p_srp_path_record;\r
630 \r
631         SRP_ENTER( SRP_DBG_PNP );\r
632 \r
633         p_srp_path_record = __srp_find_path( p_hba, p_path_rec, TRUE, TRUE );\r
634         if ( p_srp_path_record != NULL )\r
635         {\r
636                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
637 \r
638                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
639                         ("Removing path record (slid:0x%x dlid:0x%x) for %s.\n",\r
640                         cl_ntoh16(p_path_rec->slid),\r
641                         cl_ntoh16(p_path_rec->dlid),\r
642                         p_hba->ioc_info.profile.id_string) );\r
643 \r
644                 cl_qlist_remove_item( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
645 \r
646                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
647         }\r
648 \r
649         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
650                 ("Current Path count for %s = %d \n",\r
651                  p_hba->ioc_info.profile.id_string,\r
652                  (int)cl_qlist_count( &p_hba->path_record_list )) );\r
653 \r
654         SRP_EXIT( SRP_DBG_PNP );\r
655 \r
656         return p_srp_path_record;\r
657 }\r
658 \r
659 static\r
660 srp_path_record_t*\r
661 __srp_add_path(\r
662         IN  srp_hba_t               *p_hba,\r
663         IN  const ib_path_rec_t     *p_path_rec )\r
664 {\r
665         srp_path_record_t   *p_srp_path_record;\r
666 \r
667         SRP_ENTER( SRP_DBG_PNP );\r
668 \r
669         p_srp_path_record = __srp_find_path( p_hba, p_path_rec, FALSE, FALSE );\r
670         if ( p_srp_path_record != NULL )\r
671         {\r
672                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
673                 p_srp_path_record->path_rec = *p_path_rec;\r
674                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
675 \r
676                 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,\r
677                         ("Discarding/Updating duplicate path record (slid:0x%x dlid:0x%x) for %s.\n",\r
678                         cl_ntoh16(p_path_rec->slid),\r
679                         cl_ntoh16(p_path_rec->dlid),\r
680                         p_hba->ioc_info.profile.id_string) );\r
681 \r
682                 goto exit;\r
683         }\r
684 \r
685         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
686                 ("Adding path record (slid:0x%x dlid:0x%x) for %s.\n",\r
687                 cl_ntoh16(p_path_rec->slid),\r
688                 cl_ntoh16(p_path_rec->dlid),\r
689                 p_hba->ioc_info.profile.id_string) );\r
690 \r
691 \r
692         p_srp_path_record = cl_zalloc( sizeof( srp_path_record_t ) );\r
693         if ( p_srp_path_record == NULL )\r
694         {\r
695                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
696                         ("Insufficient Memory.\n") );\r
697         }\r
698         else\r
699         {\r
700                 p_srp_path_record->path_rec = *p_path_rec;\r
701 \r
702                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
703                 cl_qlist_insert_tail( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
704                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
705         }\r
706 \r
707         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
708                 ("Current Path count for %s = %d \n",\r
709                  p_hba->ioc_info.profile.id_string,\r
710                  (int)cl_qlist_count( &p_hba->path_record_list )) );\r
711 \r
712 exit:\r
713         SRP_EXIT( SRP_DBG_PNP );\r
714 \r
715         return p_srp_path_record;\r
716 }\r
717 \r
718 static ib_api_status_t\r
719 __srp_connect_sessions(\r
720         IN OUT srp_hba_t    *p_hba )\r
721 {\r
722         uint32_t        i;\r
723         srp_session_t   *p_session;\r
724         ib_api_status_t status = IB_ERROR;\r
725         BOOLEAN any_ioc_connected = FALSE;\r
726 \r
727         SRP_ENTER( SRP_DBG_PNP );\r
728 \r
729         /* Create the session(s). */\r
730         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
731         {\r
732                 int     retry_count = 0;\r
733 \r
734                 do{\r
735                         retry_count++;\r
736 \r
737                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
738                         ("Creating New Session For Service Entry Index %d.\n", i ));\r
739 \r
740                         p_session = srp_new_session(\r
741                                                         p_hba, \r
742                                                         &p_hba->p_svc_entries[i],\r
743                                                         &p_hba->p_srp_path_record->path_rec,\r
744                                                         &status );\r
745                         if( p_session == NULL )\r
746                         {\r
747                                 status = IB_INSUFFICIENT_MEMORY;\r
748                                 break;\r
749                         }\r
750 \r
751                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
752                         ("New Session For Service Entry Index %d Created.\n", i ));\r
753 \r
754                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
755                                 ("Attempting to connect %s. Svc Idx %d; Connection Attempt Count = %d.\n", \r
756                                  p_hba->ioc_info.profile.id_string, i,\r
757                                  retry_count) );\r
758                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
759                                 ("Logging Into Session.\n"));\r
760                         status = srp_session_login( p_session );\r
761                         if ( status == IB_SUCCESS )\r
762                         {\r
763                                 any_ioc_connected = TRUE;\r
764 \r
765                                 srp_session_adjust_params( p_session );\r
766 \r
767                                 cl_obj_lock( &p_hba->obj );\r
768                                 p_session->target_id = (UCHAR)i;\r
769                                 p_hba->session_list[i] = p_session;\r
770                                 cl_obj_unlock( &p_hba->obj );\r
771 \r
772                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
773                                         ("Session Login Issued Successfully.\n"));\r
774                         }\r
775                         else\r
776                         {\r
777                                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_PNP,\r
778                                         ("Session Login for Service Idx %d Failure Status = %d.\n", i, status));\r
779                                 cl_obj_destroy( &p_session->obj );\r
780                         }\r
781 \r
782                 } while ( (status != IB_SUCCESS) && (retry_count < 3) );\r
783 \r
784         }\r
785 \r
786         if ( any_ioc_connected == TRUE )\r
787         {\r
788                 status = IB_SUCCESS;\r
789                 for( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
790                 {\r
791                         p_session = p_hba->session_list[i];\r
792                         \r
793                         if( p_session != NULL &&\r
794                                 p_session->connection.state == SRP_CONNECTED && \r
795                                 p_hba->session_paused[i] == TRUE )\r
796                         {\r
797                                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
798                                 ("Resuming Adapter Session %d for %s.\n", i,\r
799                                                 p_hba->ioc_info.profile.id_string) );\r
800 \r
801                                 p_hba->session_paused[i] = FALSE;\r
802                                 StorPortDeviceReady( p_hba->p_ext, SP_UNTAGGED, (UCHAR)i, SP_UNTAGGED );\r
803                         }\r
804                 }\r
805         }\r
806 \r
807         SRP_EXIT( SRP_DBG_PNP );\r
808 \r
809         return status;\r
810 }\r
811 \r
812 void\r
813 srp_disconnect_sessions(\r
814         IN                              srp_hba_t                                       *p_hba )\r
815 {\r
816         uint32_t                i;\r
817         srp_session_t   *p_session;\r
818 \r
819         SRP_ENTER( SRP_DBG_PNP );\r
820 \r
821         cl_obj_lock( &p_hba->obj );\r
822 \r
823         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
824         {\r
825                 if ( p_hba->session_list[i] != NULL )\r
826                 {\r
827                         p_session = p_hba->session_list[i];\r
828                         p_hba->session_list[i] = NULL;\r
829                         p_session->connection.state = SRP_CONNECT_FAILURE;\r
830                         srp_session_failed( p_session );\r
831                 }\r
832         }\r
833 \r
834         cl_obj_unlock( &p_hba->obj );\r
835 \r
836         SRP_EXIT( SRP_DBG_PNP );\r
837 }\r
838 \r
839 static ib_api_status_t\r
840 __srp_connect_path(\r
841         IN  srp_hba_t   *p_hba )\r
842 {\r
843         ib_api_status_t     status = IB_ERROR;\r
844         srp_path_record_t   *p_srp_path_record;\r
845 \r
846         SRP_ENTER( SRP_DBG_PNP );\r
847 \r
848         while ( g_srp_system_shutdown == FALSE )\r
849         {\r
850                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
851                         ("Searching for path to %s.\n",\r
852                          p_hba->ioc_info.profile.id_string) );\r
853 \r
854                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
855                 p_srp_path_record = (srp_path_record_t *)cl_qlist_head( &p_hba->path_record_list );\r
856                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
857                 if ( p_srp_path_record == (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
858                 {\r
859                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
860                                 ("No paths to %s found.\n",\r
861                                 p_hba->ioc_info.profile.id_string) );\r
862                         break;\r
863                 }\r
864 \r
865                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
866                         ("Connecting path to %s.\n",\r
867                         p_hba->ioc_info.profile.id_string) );\r
868 \r
869                 p_hba->p_srp_path_record = p_srp_path_record;\r
870                 status = __srp_connect_sessions( p_hba );\r
871                 if ( status == IB_SUCCESS )\r
872                 {\r
873                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
874                                 ("Path to %s has connected.\n",\r
875                                 p_hba->ioc_info.profile.id_string) );\r
876                         break;\r
877                 }\r
878 \r
879                 p_hba->p_srp_path_record = NULL;\r
880                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
881                 cl_qlist_remove_item( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
882                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
883                 cl_free( p_srp_path_record );\r
884         }\r
885 \r
886         SRP_EXIT( SRP_DBG_PNP );\r
887 \r
888         return status;\r
889 }\r
890 \r
891 static ib_api_status_t\r
892 __srp_pnp_cb(\r
893         IN              ib_pnp_rec_t                *p_pnp_rec )\r
894 {\r
895         ib_api_status_t                 status = IB_SUCCESS;\r
896         ib_pnp_ioc_rec_t                *p_ioc_rec;\r
897         ib_pnp_ioc_path_rec_t   *p_ioc_path;\r
898         srp_hba_t                               *p_hba;\r
899         srp_path_record_t               *p_srp_path_record;\r
900         \r
901         SRP_ENTER( SRP_DBG_PNP );\r
902 \r
903         p_hba = (srp_hba_t*)p_pnp_rec->pnp_context;\r
904         p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
905         p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
906 \r
907         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
908                 ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
909                 p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
910 \r
911 \r
912         switch( p_pnp_rec->pnp_event )\r
913         {\r
914                 case IB_PNP_IOC_ADD:\r
915                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
916                                 ("IB_PNP_IOC_ADD for %s.\n",\r
917                                 p_ioc_rec->info.profile.id_string) );\r
918 \r
919                         __srp_dump_ioc_info( &p_ioc_rec->info );\r
920 \r
921                         /*\r
922                          * Trap our CA GUID so we filter path notifications\r
923                          * for our bound CA only.\r
924                          */\r
925                         if( p_ioc_rec->ca_guid != p_hba->info.ca_guid )\r
926                         {\r
927                                 SRP_PRINT_EXIT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,\r
928                                         ("Ignoring CA GUID.\n") );\r
929                                 status = IB_INVALID_GUID;\r
930                                 break;\r
931                         }\r
932 \r
933                         /* Trap our IOC GUID so we can get path notification events. */\r
934                         if( p_ioc_rec->info.profile.ioc_guid != p_hba->info.guid )\r
935                         {\r
936                                 SRP_PRINT_EXIT( TRACE_LEVEL_WARNING, SRP_DBG_PNP,\r
937                                         ("Ignoring GUID.\n") );\r
938                                 status = IB_INVALID_GUID;\r
939                                 break;\r
940                         }\r
941 \r
942                         if ( __srp_validate_ioc( p_ioc_rec ) == FALSE )\r
943                         {\r
944                                 status = IB_INVALID_GUID;\r
945                                 break;\r
946                         }\r
947 \r
948                         p_hba->ioc_info = p_ioc_rec->info;\r
949                         p_hba->p_svc_entries = cl_zalloc( sizeof(ib_svc_entry_t) * p_hba->ioc_info.profile.num_svc_entries );\r
950                         if ( p_hba->p_svc_entries == NULL )\r
951                         {\r
952                                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
953                                         ("Insufficient Memory.\n") );\r
954                                 status = IB_INSUFFICIENT_MEMORY;\r
955                                 break;\r
956                         }\r
957 \r
958                         cl_memcpy ( p_hba->p_svc_entries,\r
959                                                 p_ioc_rec->svc_entry_array,\r
960                                                 sizeof(ib_svc_entry_t) * p_hba->ioc_info.profile.num_svc_entries);\r
961 \r
962                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
963                                 ("Found %d Service Entries.\n",\r
964                                 p_hba->ioc_info.profile.num_svc_entries));\r
965                         break;\r
966 \r
967                 case IB_PNP_IOC_REMOVE:\r
968                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
969                                 ("IB_PNP_IOC_REMOVE for %s.\n",\r
970                                 p_hba->ioc_info.profile.id_string) );\r
971 \r
972                         CL_ASSERT( p_pnp_rec->guid == p_hba->info.guid );\r
973 \r
974                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
975                                 ("Hey!!! Our IOC went away.\n") );\r
976                         \r
977                         if( !p_hba->adapter_stopped )\r
978                                 p_hba->adapter_stopped = TRUE;\r
979                         \r
980                         srp_disconnect_sessions( p_hba );\r
981                         __srp_remove_path_records( p_hba );\r
982 \r
983                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
984                                 ("IB_PNP_IOC_REMOVE HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt ) );\r
985 \r
986                         break;\r
987 \r
988                 case IB_PNP_IOC_PATH_ADD:\r
989                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
990                                 ("IB_PNP_IOC_PATH_ADD (slid:0x%x dlid:0x%x) for %s.\n",\r
991                                 cl_ntoh16(p_ioc_path->path.slid),\r
992                                 cl_ntoh16(p_ioc_path->path.dlid),\r
993                                 p_hba->ioc_info.profile.id_string));\r
994 \r
995                         p_srp_path_record = __srp_add_path( p_hba, &p_ioc_path->path );\r
996                         if ( p_srp_path_record == NULL )\r
997                         {\r
998                                 status = IB_INSUFFICIENT_MEMORY;\r
999                                 break;\r
1000                         }\r
1001 \r
1002                         if ( p_hba->p_srp_path_record == NULL )\r
1003                         {\r
1004                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
1005                                         ("Connecting new path to %s.\n",\r
1006                                         p_hba->ioc_info.profile.id_string) );\r
1007                                 status = __srp_connect_path( p_hba );\r
1008                         }\r
1009 \r
1010                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
1011                                 (" IOC_PATH ADD HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt ) );\r
1012                         break;\r
1013 \r
1014                 case IB_PNP_IOC_PATH_REMOVE:\r
1015                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
1016                                 ("IB_PNP_IOC_PATH_REMOVE (slid:%x dlid:%x) for %s.\n",\r
1017                                 cl_ntoh16(p_ioc_path->path.slid),\r
1018                                 cl_ntoh16(p_ioc_path->path.dlid),\r
1019                                 p_hba->ioc_info.profile.id_string));\r
1020 \r
1021                         p_srp_path_record = __srp_remove_path( p_hba, &p_ioc_path->path );\r
1022                         if ( p_srp_path_record != NULL )\r
1023                         {\r
1024                                 if ( p_srp_path_record == p_hba->p_srp_path_record )\r
1025                                 {\r
1026                                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_PNP,\r
1027                                                 ("Current path to %s has been lost.\n",\r
1028                                                  p_hba->ioc_info.profile.id_string) );\r
1029 \r
1030                                         if ( g_srp_system_shutdown == FALSE )\r
1031                                         {\r
1032                                                 srp_disconnect_sessions( p_hba );\r
1033                                         }\r
1034                                 }\r
1035 \r
1036                                 cl_free( p_srp_path_record );\r
1037                         }\r
1038                         break;\r
1039 \r
1040                 default:\r
1041                         CL_ASSERT( p_pnp_rec->pnp_event == IB_PNP_IOC_ADD ||\r
1042                                 p_pnp_rec->pnp_event == IB_PNP_IOC_REMOVE ||\r
1043                                 p_pnp_rec->pnp_event == IB_PNP_IOC_PATH_ADD ||\r
1044                                 p_pnp_rec->pnp_event == IB_PNP_IOC_PATH_REMOVE );\r
1045                         break;\r
1046         }\r
1047 \r
1048         SRP_EXIT( SRP_DBG_PNP );\r
1049         return status;\r
1050 }\r