dbcad9ec5b81b05172881c7b4f262356a4360f60
[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( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
250                         ("HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
251                 cl_obj_destroy( &p_hba->obj );\r
252                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
253                         ("ib_open_al returned %s\n", p_hba->ifc.get_err_str( ib_status )) );\r
254                 return ib_status;\r
255         }\r
256 \r
257         /* Register for IOC events */\r
258         pnp_req.pfn_pnp_cb = __srp_pnp_cb;\r
259         pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC;\r
260         pnp_req.pnp_context = p_hba;\r
261         /* Reference the HBA object before registering for PnP notifications. */\r
262         cl_obj_ref( &p_hba->obj );\r
263 \r
264         cl_obj_insert_rel( &p_hba->rel, p_drv_obj, &p_hba->obj );\r
265 \r
266         ib_status = p_hba->ifc.reg_pnp( p_hba->h_al, &pnp_req, &p_hba->h_pnp );\r
267         if( ib_status != IB_SUCCESS )\r
268         {\r
269                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
270                         ("HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
271                 cl_obj_destroy( &p_hba->obj );\r
272                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
273                         ("ib_reg_pnp returned %s\n", p_hba->ifc.get_err_str( ib_status )) );\r
274                 return ib_status;\r
275         }\r
276 \r
277         /*\r
278          * Add the HBA to the driver object's child list.  This will cause\r
279          * everything to clean up properly in case we miss an unload notification.\r
280          */\r
281         p_ext->p_hba = p_hba;\r
282 \r
283         if ( p_hba->session_list[0] == NULL )\r
284         {\r
285                 p_ext->p_hba = NULL;\r
286                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
287                         ("HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
288                 cl_obj_destroy( &p_hba->obj );\r
289 \r
290                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
291                         ("Session Connection Failure.\n") );\r
292                 ib_status = IB_ERROR;\r
293         }\r
294 \r
295         SRP_EXIT( SRP_DBG_PNP );\r
296         return ib_status;\r
297 }\r
298 \r
299 \r
300 static void\r
301 __srp_destroying_hba(\r
302         IN              cl_obj_t                    *p_obj )\r
303 {\r
304         srp_hba_t       *p_hba;\r
305 \r
306         SRP_ENTER( SRP_DBG_PNP );\r
307 \r
308         p_hba = PARENT_STRUCT( p_obj, srp_hba_t, obj );\r
309 \r
310         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
311                 ("Before dereg pnp HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
312 \r
313         if( p_hba->h_pnp )\r
314         {\r
315                 p_hba->ifc.dereg_pnp( p_hba->h_pnp, cl_obj_deref );\r
316         }\r
317 \r
318         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
319                 ("After dereg pnp HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
320 \r
321         SRP_EXIT( SRP_DBG_PNP );\r
322 }\r
323 \r
324 static void\r
325 __srp_remove_path_records(\r
326         IN              srp_hba_t                   *p_hba )\r
327 {\r
328         srp_path_record_t   *p_srp_path_record;\r
329 \r
330         SRP_ENTER( SRP_DBG_PNP );\r
331 \r
332         cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
333         p_srp_path_record = (srp_path_record_t *)cl_qlist_remove_head( &p_hba->path_record_list );\r
334 \r
335         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
336                 ("Removing any remaining path records.\n") );\r
337 \r
338         while ( p_srp_path_record != (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
339         {\r
340                 cl_free( p_srp_path_record );\r
341                 p_srp_path_record = (srp_path_record_t *)cl_qlist_remove_head( &p_hba->path_record_list );\r
342         }\r
343 \r
344         cl_spinlock_release( &p_hba->path_record_list_lock );\r
345 \r
346         SRP_EXIT( SRP_DBG_PNP );\r
347 }\r
348 \r
349 static void\r
350 __srp_cleanup_hba(\r
351         IN              cl_obj_t                    *p_obj )\r
352 {\r
353         srp_hba_t   *p_hba;\r
354 \r
355         SRP_ENTER( SRP_DBG_PNP );\r
356 \r
357         p_hba = PARENT_STRUCT( p_obj, srp_hba_t, obj );\r
358 \r
359         if( p_hba->h_al )\r
360                 p_hba->ifc.close_al( p_hba->h_al );\r
361 \r
362         __srp_remove_path_records( p_hba );\r
363 \r
364         cl_spinlock_destroy( &p_hba->path_record_list_lock );\r
365 \r
366         if ( p_hba->p_svc_entries )\r
367                 cl_free( p_hba->p_svc_entries );\r
368 \r
369         SRP_EXIT( SRP_DBG_PNP );\r
370 }\r
371 \r
372 \r
373 static void\r
374 __srp_free_hba(\r
375         IN              cl_obj_t                    *p_obj )\r
376 {\r
377         srp_hba_t       *p_hba;\r
378 \r
379         SRP_ENTER( SRP_DBG_PNP );\r
380 \r
381         p_hba = PARENT_STRUCT( p_obj, srp_hba_t, obj );\r
382 \r
383         cl_obj_deinit( p_obj );\r
384         cl_free( p_hba );\r
385 \r
386         SRP_EXIT( SRP_DBG_PNP );\r
387 }\r
388 \r
389 static BOOLEAN\r
390 __srp_validate_ioc(\r
391         IN  ib_pnp_ioc_rec_t    *p_ioc_rec )\r
392 {\r
393         SRP_ENTER( SRP_DBG_PNP );\r
394 \r
395         // Is this really an SRP device?\r
396         if ( ( cl_ntoh16( p_ioc_rec->info.profile.io_class )  != SRP_IO_CLASS &&\r
397                    cl_ntoh16( p_ioc_rec->info.profile.io_class )  != SRP_IO_CLASS_R10 ) ||\r
398                  cl_ntoh16( p_ioc_rec->info.profile.io_subclass ) != SRP_IO_SUBCLASS )\r
399         {\r
400                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
401                                                 ("Not an SRP CLASS(0x%x)/SUBCLASS(0x%x).\n",\r
402                                                 cl_ntoh16( p_ioc_rec->info.profile.io_class ),\r
403                                                 cl_ntoh16( p_ioc_rec->info.profile.io_subclass )) );\r
404                 return FALSE;\r
405         }\r
406 \r
407         // Does it have the required features?\r
408         if ( cl_ntoh16( p_ioc_rec->info.profile.protocol )     != SRP_PROTOCOL     ||\r
409                  cl_ntoh16( p_ioc_rec->info.profile.protocol_ver ) != SRP_PROTOCOL_VER ||\r
410                  !(p_ioc_rec->info.profile.ctrl_ops_cap & CTRL_OPS_CAP_ST) ||\r
411                  !(p_ioc_rec->info.profile.ctrl_ops_cap & CTRL_OPS_CAP_SF) ||\r
412                  !(p_ioc_rec->info.profile.ctrl_ops_cap & CTRL_OPS_CAP_RF) ||\r
413                  !(p_ioc_rec->info.profile.ctrl_ops_cap & CTRL_OPS_CAP_WF) )\r
414         {\r
415                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
416                         ("Not an SRP PROTOCOL/PROTOCOL_VER.\n") );\r
417                 return FALSE;\r
418         }\r
419 \r
420         // Can it handle our IO requirements?\r
421         if ( cl_ntoh32( p_ioc_rec->info.profile.send_msg_size )  <  SRP_MIN_TGT_TO_INI_IU ||\r
422                  cl_ntoh16( p_ioc_rec->info.profile.send_msg_depth ) == 0 ||\r
423                  cl_ntoh32( p_ioc_rec->info.profile.rdma_size )      <  SRP_MIN_TGT_TO_INI_DMA )\r
424         {\r
425                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
426                         ("Device Not Capable.\n") );\r
427                 return FALSE;\r
428         }\r
429 \r
430         SRP_EXIT( SRP_DBG_PNP );\r
431 \r
432         return TRUE;\r
433 }\r
434 \r
435 static BOOLEAN\r
436 __srp_path_rec_equal(\r
437         IN      const ib_path_rec_t     *p_path_rec_1,\r
438         IN      const ib_path_rec_t     *p_path_rec_2,\r
439         IN      BOOLEAN                         check_num_path,\r
440         IN      BOOLEAN                         check_preference )\r
441 {\r
442         SRP_ENTER( SRP_DBG_PNP );\r
443 \r
444         if ( p_path_rec_1->dgid.unicast.prefix != p_path_rec_2->dgid.unicast.prefix )\r
445                 return ( FALSE );\r
446 \r
447         if ( p_path_rec_1->dgid.unicast.interface_id != p_path_rec_2->dgid.unicast.interface_id )\r
448                 return ( FALSE );\r
449 \r
450         if ( p_path_rec_1->sgid.unicast.prefix != p_path_rec_2->sgid.unicast.prefix )\r
451                 return ( FALSE );\r
452 \r
453         if ( p_path_rec_1->sgid.unicast.interface_id != p_path_rec_2->sgid.unicast.interface_id )\r
454                 return ( FALSE );\r
455 \r
456         if ( p_path_rec_1->dlid != p_path_rec_2->dlid )\r
457                 return ( FALSE );\r
458 \r
459         if ( p_path_rec_1->slid != p_path_rec_2->slid )\r
460                 return ( FALSE );\r
461 \r
462         if ( p_path_rec_1->hop_flow_raw.val != p_path_rec_2->hop_flow_raw.val )\r
463         {\r
464                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
465                         ("hop_flow_raw.val does not match.\n") );\r
466                 return ( FALSE );\r
467         }\r
468 \r
469         if ( p_path_rec_1->tclass != p_path_rec_2->tclass )\r
470         {\r
471                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
472                         ("tclass does not match.\n") );\r
473                 return ( FALSE );\r
474         }\r
475 \r
476         if ( p_path_rec_1->num_path != p_path_rec_2->num_path )\r
477         {\r
478                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
479                         ("num_path does not match.\n") );\r
480                 if ( check_num_path == TRUE )\r
481                 {\r
482                         return ( FALSE );\r
483                 }\r
484         }\r
485 \r
486         if ( p_path_rec_1->pkey != p_path_rec_2->pkey )\r
487         {\r
488                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
489                         ("pkey does not match.\n") );\r
490                 return ( FALSE );\r
491         }\r
492 \r
493         if ( p_path_rec_1->sl != p_path_rec_2->sl )\r
494         {\r
495                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
496                         ("sl does not match.\n") );\r
497                 return ( FALSE );\r
498         }\r
499 \r
500         if ( p_path_rec_1->mtu != p_path_rec_2->mtu )\r
501         {\r
502                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
503                         ("mtu does not match.\n") );\r
504                 return ( FALSE );\r
505         }\r
506 \r
507         if ( p_path_rec_1->rate != p_path_rec_2->rate )\r
508         {\r
509                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
510                         ("rate does not match.\n") );\r
511                 return ( FALSE );\r
512         }\r
513 \r
514         if ( p_path_rec_1->pkt_life != p_path_rec_2->pkt_life )\r
515         {\r
516                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
517                         ("pkt_life does not match.\n") );\r
518                 return ( FALSE );\r
519         }\r
520 \r
521         if ( p_path_rec_1->preference != p_path_rec_2->preference )\r
522         {\r
523                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
524                         ("preference does not match.\n") );\r
525                 if ( check_preference == TRUE )\r
526                 {\r
527                         return ( FALSE );\r
528                 }\r
529         }\r
530 \r
531 #if defined( _DEBUG_ )\r
532 \r
533         if ( p_path_rec_1->resv0 != p_path_rec_2->resv0 )\r
534         {\r
535                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
536                         ("resv0 does not match.\n") );\r
537         }\r
538 \r
539         if ( p_path_rec_1->resv1 != p_path_rec_2->resv1 )\r
540         {\r
541                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
542                         ("resv1 does not match.\n") );\r
543         }\r
544 \r
545         if ( p_path_rec_1->resv2 != p_path_rec_2->resv2 )\r
546         {\r
547                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
548                         ("resv2 does not match.\n") );\r
549         }\r
550 \r
551         if ( cl_memcmp( p_path_rec_1, p_path_rec_2, sizeof( ib_path_rec_t ) ) != 0 )\r
552         {\r
553                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
554                         ("p_path_rec_1 does not match p_path_rec_2.\n") );\r
555         }\r
556         else\r
557         {\r
558                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
559                         ("p_path_rec_1 matches p_path_rec_2.\n") );\r
560         }\r
561 \r
562 #endif\r
563 \r
564         SRP_EXIT( SRP_DBG_PNP );\r
565 \r
566         return ( TRUE );\r
567 }\r
568 \r
569 static\r
570 srp_path_record_t*\r
571 __srp_find_path(\r
572         IN  srp_hba_t               *p_hba,\r
573         IN  const ib_path_rec_t     *p_path_rec,\r
574         IN  BOOLEAN                 check_num_path,\r
575         IN  BOOLEAN                 check_preference )\r
576 {\r
577         srp_path_record_t   *p_srp_path_record;\r
578 \r
579         SRP_ENTER( SRP_DBG_PNP );\r
580 \r
581         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
582                 ("Finding path record (slid:%d dlid:%d) for %s.\n",\r
583                 p_path_rec->slid,\r
584                 p_path_rec->dlid,\r
585                 p_hba->ioc_info.profile.id_string) );\r
586 \r
587         cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
588 \r
589         p_srp_path_record = (srp_path_record_t *)cl_qlist_head( &p_hba->path_record_list );\r
590 \r
591         while ( p_srp_path_record != (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
592         {\r
593                 if ( __srp_path_rec_equal( (const ib_path_rec_t *)&p_srp_path_record->path_rec,\r
594                                                                         p_path_rec,\r
595                                                                         check_num_path,\r
596                                                                         check_preference ) == TRUE )\r
597                 {\r
598                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
599                                 ("Found path record (slid:%d dlid:%d) for %s.\n",\r
600                                 p_path_rec->slid,\r
601                                 p_path_rec->dlid,\r
602                                 p_hba->ioc_info.profile.id_string) );\r
603                         break;\r
604                 }\r
605 \r
606                 p_srp_path_record = (srp_path_record_t *)cl_qlist_next( &p_srp_path_record->list_item );\r
607         }\r
608 \r
609         if ( p_srp_path_record == (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
610         {\r
611                 p_srp_path_record = NULL;\r
612         }\r
613 \r
614         cl_spinlock_release( &p_hba->path_record_list_lock );\r
615 \r
616         SRP_EXIT( SRP_DBG_PNP );\r
617 \r
618         return p_srp_path_record;\r
619 }\r
620 \r
621 static\r
622 srp_path_record_t*\r
623 __srp_remove_path(\r
624         IN  srp_hba_t               *p_hba,\r
625         IN  const ib_path_rec_t     *p_path_rec )\r
626 {\r
627         srp_path_record_t   *p_srp_path_record;\r
628 \r
629         SRP_ENTER( SRP_DBG_PNP );\r
630 \r
631         p_srp_path_record = __srp_find_path( p_hba, p_path_rec, TRUE, TRUE );\r
632         if ( p_srp_path_record != NULL )\r
633         {\r
634                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
635 \r
636                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
637                         ("Removing path record (slid:%d dlid:%d) for %s.\n",\r
638                         p_path_rec->slid,\r
639                         p_path_rec->dlid,\r
640                         p_hba->ioc_info.profile.id_string) );\r
641 \r
642                 cl_qlist_remove_item( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
643 \r
644                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
645         }\r
646 \r
647         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
648                 ("Current Path count for %s = %d \n",\r
649                  p_hba->ioc_info.profile.id_string,\r
650                  (int)cl_qlist_count( &p_hba->path_record_list )) );\r
651 \r
652         SRP_EXIT( SRP_DBG_PNP );\r
653 \r
654         return p_srp_path_record;\r
655 }\r
656 \r
657 static\r
658 srp_path_record_t*\r
659 __srp_add_path(\r
660         IN  srp_hba_t               *p_hba,\r
661         IN  const ib_path_rec_t     *p_path_rec )\r
662 {\r
663         srp_path_record_t   *p_srp_path_record;\r
664 \r
665         SRP_ENTER( SRP_DBG_PNP );\r
666 \r
667         p_srp_path_record = __srp_find_path( p_hba, p_path_rec, FALSE, FALSE );\r
668         if ( p_srp_path_record != NULL )\r
669         {\r
670                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
671                 p_srp_path_record->path_rec = *p_path_rec;\r
672                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
673 \r
674                 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DEBUG,\r
675                         ("Discarding/Updating duplicate path record (slid:%d dlid:%d) for %s.\n",\r
676                         p_path_rec->slid,\r
677                         p_path_rec->dlid,\r
678                         p_hba->ioc_info.profile.id_string) );\r
679 \r
680                 goto exit;\r
681         }\r
682 \r
683         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
684                 ("Adding path record (slid:%d dlid:%d) for %s.\n",\r
685                 p_path_rec->slid,\r
686                 p_path_rec->dlid,\r
687                 p_hba->ioc_info.profile.id_string) );\r
688 \r
689 \r
690         p_srp_path_record = cl_zalloc( sizeof( srp_path_record_t ) );\r
691         if ( p_srp_path_record == NULL )\r
692         {\r
693                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
694                         ("Insufficient Memory.\n") );\r
695         }\r
696         else\r
697         {\r
698                 p_srp_path_record->path_rec = *p_path_rec;\r
699 \r
700                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
701                 cl_qlist_insert_tail( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
702                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
703         }\r
704 \r
705         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
706                 ("Current Path count for %s = %d \n",\r
707                  p_hba->ioc_info.profile.id_string,\r
708                  (int)cl_qlist_count( &p_hba->path_record_list )) );\r
709 \r
710 exit:\r
711         SRP_EXIT( SRP_DBG_PNP );\r
712 \r
713         return p_srp_path_record;\r
714 }\r
715 \r
716 static ib_api_status_t\r
717 __srp_connect_sessions(\r
718         IN OUT srp_hba_t    *p_hba )\r
719 {\r
720         uint32_t        i;\r
721         srp_session_t   *p_session;\r
722         ib_api_status_t status = IB_ERROR;\r
723 \r
724         SRP_ENTER( SRP_DBG_PNP );\r
725 \r
726         /* Create the session(s). */\r
727         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
728         {\r
729                 BOOLEAN any_ioc_connected = FALSE;\r
730                 int     retry_count = 0;\r
731 \r
732                 do\r
733                 {\r
734                         retry_count++;\r
735 \r
736                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
737                                 ("Attempting to connect %s. Connection Attempt Count = %d.\n",\r
738                                  p_hba->ioc_info.profile.id_string,\r
739                                  retry_count) );\r
740 \r
741                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
742                                 ("Creating New Session For Service Entry Index %d.\n",\r
743                                 p_hba->ioc_info.profile.num_svc_entries));\r
744                         p_session = srp_new_session( p_hba,\r
745                                                                                  p_hba->ioc_info.profile.ioc_guid,\r
746                                                                                  &p_hba->p_svc_entries[i],\r
747                                                                                  &status );\r
748                         if ( p_session == NULL )\r
749                         {\r
750                                 status = IB_INSUFFICIENT_MEMORY;\r
751                                 break;\r
752                         }\r
753 \r
754                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
755                                 ("New Session For Service Entry Index %d Created.\n",\r
756                                 p_hba->ioc_info.profile.num_svc_entries));\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                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
792                                         ("Session Object ref_cnt = %d\n", p_session->obj.ref_cnt) );\r
793                                 cl_obj_destroy( &p_session->obj );\r
794                         }\r
795                 } while ( (status != IB_SUCCESS) && (retry_count < 3) );\r
796 \r
797                 if ( any_ioc_connected == TRUE )\r
798                 {\r
799                         status = IB_SUCCESS;\r
800                         if ( p_hba->adapter_paused == TRUE )\r
801                         {\r
802                                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
803                                         ("Resuming Adapter for %s.\n",\r
804                                         p_hba->ioc_info.profile.id_string) );\r
805                                 p_hba->adapter_paused = FALSE;\r
806                                 StorPortReady( p_hba->p_ext );\r
807 //                              StorPortNotification( BusChangeDetected, p_hba->p_ext, 0 );\r
808                         }\r
809                 }\r
810         }\r
811 \r
812         SRP_EXIT( SRP_DBG_PNP );\r
813 \r
814         return status;\r
815 }\r
816 \r
817 static void\r
818 __srp_disconnect_sessions(\r
819         IN                              srp_hba_t                                       *p_hba,\r
820         IN                              BOOLEAN                                         pause_adapter )\r
821 {\r
822         uint32_t                i;\r
823         srp_session_t   *p_session;\r
824 \r
825         SRP_ENTER( SRP_DBG_PNP );\r
826 \r
827         cl_obj_lock( &p_hba->obj );\r
828 \r
829         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
830         {\r
831                 if ( p_hba->session_list[i] != NULL )\r
832                 {\r
833                         break;\r
834                 }\r
835         }\r
836 \r
837         cl_obj_unlock( &p_hba->obj );\r
838 \r
839         if ( i == p_hba->ioc_info.profile.num_svc_entries )\r
840         {\r
841                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
842                         ("No current connections to %s.\n",\r
843                         p_hba->ioc_info.profile.id_string) );\r
844                 goto exit;\r
845         }\r
846 \r
847         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
848                 ("Current path to %s has been lost.\n",\r
849                 p_hba->ioc_info.profile.id_string) );\r
850 \r
851         p_hba->p_srp_path_record = NULL;\r
852 \r
853         if ( pause_adapter == TRUE )\r
854         {\r
855                 if ( p_hba->adapter_paused == FALSE )\r
856                 {\r
857                         p_hba->adapter_paused = TRUE;\r
858                         StorPortBusy( p_hba->p_ext, (ULONG)-1 );\r
859                         StorPortCompleteRequest( p_hba->p_ext,\r
860                                                                          SP_UNTAGGED,\r
861                                                                          SP_UNTAGGED,\r
862                                                                          SP_UNTAGGED,\r
863                                                                          SRB_STATUS_BUSY );\r
864                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
865                                 ("Pausing Adapter for %s.\n",\r
866                                 p_hba->ioc_info.profile.id_string) );\r
867                 }\r
868         }\r
869 \r
870         /* Destroy all the connections. */\r
871         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
872                 ("Destroy all connections to %s.\n",\r
873                 p_hba->ioc_info.profile.id_string) );\r
874 \r
875         for ( i = 0; i < p_hba->ioc_info.profile.num_svc_entries; i++ )\r
876         {\r
877                 cl_obj_lock( &p_hba->obj );\r
878                 p_session = p_hba->session_list[i];\r
879                 p_hba->session_list[i] = NULL;\r
880                 cl_obj_unlock( &p_hba->obj );\r
881 \r
882                 if ( p_session != NULL )\r
883                 {\r
884                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
885                                 ("Session Object ref_cnt = %d\n", p_session->obj.ref_cnt) );\r
886                         __srp_cleanup_session ( &p_session->obj );\r
887                         cl_obj_destroy( &p_session->obj );\r
888                 }\r
889                 else\r
890                 {\r
891                         SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DEBUG,\r
892                                 ("Session for Target ID %d on %s is NULL.\n",\r
893                                  i,\r
894                                  p_hba->ioc_info.profile.id_string) ); // <-- OK in a shutdown or target disconnect\r
895                 }\r
896         }\r
897 \r
898 exit:\r
899         SRP_EXIT( SRP_DBG_PNP );\r
900 }\r
901 \r
902 static ib_api_status_t\r
903 __srp_connect_path(\r
904         IN  srp_hba_t   *p_hba )\r
905 {\r
906         ib_api_status_t     status = IB_ERROR;\r
907         srp_path_record_t   *p_srp_path_record;\r
908 \r
909         SRP_ENTER( SRP_DBG_PNP );\r
910 \r
911         while ( g_srp_system_shutdown == FALSE )\r
912         {\r
913                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
914                         ("Searching for path to %s.\n",\r
915                          p_hba->ioc_info.profile.id_string) );\r
916 \r
917                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
918                 p_srp_path_record = (srp_path_record_t *)cl_qlist_head( &p_hba->path_record_list );\r
919                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
920                 if ( p_srp_path_record == (srp_path_record_t *)cl_qlist_end( &p_hba->path_record_list ) )\r
921                 {\r
922                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
923                                 ("No paths to %s found.\n",\r
924                                 p_hba->ioc_info.profile.id_string) );\r
925                         break;\r
926                 }\r
927 \r
928                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
929                         ("Connecting path to %s.\n",\r
930                         p_hba->ioc_info.profile.id_string) );\r
931 \r
932                 p_hba->p_srp_path_record = p_srp_path_record;\r
933                 status = __srp_connect_sessions( p_hba );\r
934                 if ( status == IB_SUCCESS )\r
935                 {\r
936                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
937                                 ("Path to %s has connected.\n",\r
938                                 p_hba->ioc_info.profile.id_string) );\r
939                         break;\r
940                 }\r
941 \r
942                 p_hba->p_srp_path_record = NULL;\r
943                 cl_spinlock_acquire( &p_hba->path_record_list_lock );\r
944                 cl_qlist_remove_item( &p_hba->path_record_list, &p_srp_path_record->list_item );\r
945                 cl_spinlock_release( &p_hba->path_record_list_lock );\r
946                 cl_free( p_srp_path_record );\r
947         }\r
948 \r
949         SRP_EXIT( SRP_DBG_PNP );\r
950 \r
951         return status;\r
952 }\r
953 \r
954 static ib_api_status_t\r
955 __srp_pnp_cb(\r
956         IN              ib_pnp_rec_t                *p_pnp_rec )\r
957 {\r
958         ib_api_status_t                 status = IB_SUCCESS;\r
959         ib_pnp_ioc_rec_t                *p_ioc_rec;\r
960         ib_pnp_ioc_path_rec_t   *p_ioc_path;\r
961         srp_hba_t                               *p_hba;\r
962         srp_path_record_t               *p_srp_path_record;\r
963         \r
964         SRP_ENTER( SRP_DBG_PNP );\r
965 \r
966         p_hba = (srp_hba_t* __ptr64)p_pnp_rec->pnp_context;\r
967         p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
968         p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
969 \r
970         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_PNP,\r
971                 ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
972                 p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
973 \r
974 \r
975         switch( p_pnp_rec->pnp_event )\r
976         {\r
977                 case IB_PNP_IOC_ADD:\r
978                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
979                                 ("IB_PNP_IOC_ADD for %s.\n",\r
980                                 p_ioc_rec->info.profile.id_string) );\r
981 \r
982                         __srp_dump_ioc_info( &p_ioc_rec->info );\r
983 \r
984                         /*\r
985                          * Trap our CA GUID so we filter path notifications\r
986                          * for our bound CA only.\r
987                          */\r
988                         if( p_ioc_rec->ca_guid != p_hba->info.ca_guid )\r
989                         {\r
990                                 SRP_PRINT_EXIT( TRACE_LEVEL_WARNING, SRP_DBG_DEBUG,\r
991                                         ("Ignoring CA GUID.\n") );\r
992                                 status = IB_INVALID_GUID;\r
993                                 break;\r
994                         }\r
995 \r
996                         /* Trap our IOC GUID so we can get path notification events. */\r
997                         if( p_ioc_rec->info.profile.ioc_guid != p_hba->info.guid )\r
998                         {\r
999                                 SRP_PRINT_EXIT( TRACE_LEVEL_WARNING, SRP_DBG_DEBUG,\r
1000                                         ("Ignoring GUID.\n") );\r
1001                                 status = IB_INVALID_GUID;\r
1002                                 break;\r
1003                         }\r
1004 \r
1005                         if ( __srp_validate_ioc( p_ioc_rec ) == FALSE )\r
1006                         {\r
1007                                 status = IB_INVALID_GUID;\r
1008                                 break;\r
1009                         }\r
1010 \r
1011                         p_hba->ioc_info = p_ioc_rec->info;\r
1012                         p_hba->p_svc_entries = cl_zalloc( sizeof(ib_svc_entry_t) * p_hba->ioc_info.profile.num_svc_entries );\r
1013                         if ( p_hba->p_svc_entries == NULL )\r
1014                         {\r
1015                                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
1016                                         ("Insufficient Memory.\n") );\r
1017                                 status = IB_INSUFFICIENT_MEMORY;\r
1018                                 break;\r
1019                         }\r
1020 \r
1021                         cl_memcpy ( p_hba->p_svc_entries,\r
1022                                                 p_ioc_rec->svc_entry_array,\r
1023                                                 sizeof(ib_svc_entry_t) * p_hba->ioc_info.profile.num_svc_entries);\r
1024 \r
1025                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
1026                                 ("Found %d Service Entries.\n",\r
1027                                 p_hba->ioc_info.profile.num_svc_entries));\r
1028                         break;\r
1029 \r
1030                 case IB_PNP_IOC_REMOVE:\r
1031                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
1032                                 ("IB_PNP_IOC_REMOVE for %s.\n",\r
1033                                 p_hba->ioc_info.profile.id_string) );\r
1034 \r
1035                         CL_ASSERT( p_pnp_rec->guid == p_hba->info.guid );\r
1036 \r
1037                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
1038                                 ("Hey!!! Our IOC went away.\n") );\r
1039 \r
1040                         __srp_disconnect_sessions( p_hba, FALSE );\r
1041                         __srp_remove_path_records( p_hba );\r
1042                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
1043                                 ("HBA Object ref_cnt = %d\n", p_hba->obj.ref_cnt) );\r
1044                         break;\r
1045 \r
1046                 case IB_PNP_IOC_PATH_ADD:\r
1047                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
1048                                 ("IB_PNP_IOC_PATH_ADD (slid:%d dlid:%d) for %s.\n",\r
1049                                 p_ioc_path->path.slid,\r
1050                                 p_ioc_path->path.dlid,\r
1051                                 p_hba->ioc_info.profile.id_string));\r
1052 \r
1053                         p_srp_path_record = __srp_add_path( p_hba, &p_ioc_path->path );\r
1054                         if ( p_srp_path_record == NULL )\r
1055                         {\r
1056                                 status = IB_INSUFFICIENT_MEMORY;\r
1057                                 break;\r
1058                         }\r
1059 \r
1060                         if ( p_hba->p_srp_path_record == NULL )\r
1061                         {\r
1062                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
1063                                         ("Connecting new path to %s.\n",\r
1064                                         p_hba->ioc_info.profile.id_string) );\r
1065                                 status = __srp_connect_path( p_hba );\r
1066                         }\r
1067                         break;\r
1068 \r
1069                 case IB_PNP_IOC_PATH_REMOVE:\r
1070                         SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
1071                                 ("IB_PNP_IOC_PATH_REMOVE (slid:%d dlid:%d) for %s.\n",\r
1072                                 p_ioc_path->path.slid,\r
1073                                 p_ioc_path->path.dlid,\r
1074                                 p_hba->ioc_info.profile.id_string));\r
1075 \r
1076                         p_srp_path_record = __srp_remove_path( p_hba, &p_ioc_path->path );\r
1077                         if ( p_srp_path_record != NULL )\r
1078                         {\r
1079                                 if ( p_srp_path_record == p_hba->p_srp_path_record )\r
1080                                 {\r
1081                                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DEBUG,\r
1082                                                 ("Current path to %s has been lost.\n",\r
1083                                                  p_hba->ioc_info.profile.id_string) );\r
1084 \r
1085                                         if ( g_srp_system_shutdown == FALSE )\r
1086                                         {\r
1087                                                 __srp_disconnect_sessions( p_hba, TRUE );\r
1088                                                 status = __srp_connect_path( p_hba );\r
1089                                         }\r
1090                                         else\r
1091                                         {\r
1092                                                 __srp_disconnect_sessions( p_hba, FALSE );\r
1093                                         }\r
1094                                 }\r
1095 \r
1096                                 cl_free( p_srp_path_record );\r
1097                         }\r
1098                         break;\r
1099 \r
1100                 default:\r
1101                         CL_ASSERT( p_pnp_rec->pnp_event == IB_PNP_IOC_ADD ||\r
1102                                 p_pnp_rec->pnp_event == IB_PNP_IOC_REMOVE ||\r
1103                                 p_pnp_rec->pnp_event == IB_PNP_IOC_PATH_ADD ||\r
1104                                 p_pnp_rec->pnp_event == IB_PNP_IOC_PATH_REMOVE );\r
1105                         break;\r
1106         }\r
1107 \r
1108         SRP_EXIT( SRP_DBG_PNP );\r
1109         return status;\r
1110 }\r