ib_types: update SA attribute definitions
[mirror/winof/.git] / ulp / qlgcvnic / kernel / vnic_adapter.c
1 /*\r
2  * Copyright (c) 2007 QLogic Corporation.  All rights reserved.\r
3  * Portions Copyright (c) 2008 Microsoft Corporation.  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 #include <iba/ib_al.h>\r
34 #include <iba/ioc_ifc.h>\r
35 #include <complib/cl_bus_ifc.h>\r
36 #include "vnic_adapter.h"\r
37 \r
38 //#include "vnic_driver.h"\r
39 \r
40 extern struct _vnic_globals     g_vnic;\r
41 \r
42 NDIS_STATUS\r
43 vnic_get_adapter_params(\r
44         IN              NDIS_HANDLE                             h_handle,\r
45         OUT             vnic_params_t* const    p_params );\r
46 \r
47 static\r
48 NDIS_STATUS\r
49 _adapter_set_sg_size(\r
50         IN              NDIS_HANDLE             h_handle,\r
51         IN              ULONG                   mtu_size );\r
52 \r
53 NDIS_STATUS\r
54 vnic_get_adapter_interface(\r
55         IN              NDIS_HANDLE                     h_handle,\r
56         IN              vnic_adapter_t          *p_adapter);\r
57 \r
58 static\r
59 vnic_path_record_t*\r
60 __path_record_add(\r
61         IN              vnic_adapter_t* const   p_adapter,\r
62         IN              ib_path_rec_t* const    p_path_rec );\r
63 \r
64 static \r
65 vnic_path_record_t*\r
66 __path_record_remove(\r
67         IN              vnic_adapter_t* const   p_adapter,\r
68         IN              ib_path_rec_t* const    p_path_rec );\r
69 \r
70 static BOOLEAN\r
71 __path_records_match(\r
72         IN              ib_path_rec_t* const    p_path1,\r
73         IN              ib_path_rec_t* const    p_path2 );\r
74 \r
75 static\r
76 vnic_path_record_t *\r
77 __path_record_find( \r
78         IN              vnic_adapter_t* const   p_adapter,\r
79         IN              ib_path_rec_t* const    p_path_rec );\r
80 \r
81 static\r
82 vnic_path_record_t*\r
83 __path_record_get(\r
84         IN              vnic_adapter_t* const   p_adapter );\r
85 \r
86 static void\r
87 __path_records_cleanup(\r
88         IN      vnic_adapter_t  *p_adapter );\r
89 \r
90 static ib_api_status_t\r
91 _adapter_open_ca(\r
92         IN              vnic_adapter_t* const   p_adapter );\r
93 \r
94 \r
95 static ib_api_status_t\r
96 _adapter_close_ca(\r
97         IN              vnic_adapter_t* const   p_adapter );\r
98 \r
99 static \r
100 ib_api_status_t\r
101 _adapter_netpath_update(\r
102         IN              vnic_adapter_t* const   p_adapter,\r
103         IN              viport_t* const                 p_viport,\r
104         IN              vnic_path_record_t*             p_path );\r
105 \r
106 static\r
107 ib_api_status_t\r
108 adapter_netpath_update_and_connect(\r
109         IN              vnic_adapter_t* const   p_adapter,\r
110         IN              vnic_path_record_t              *p_path );\r
111 \r
112 static inline uint8_t\r
113 _get_ioc_num_from_iocguid(\r
114         IN              ib_net64_t              *p_iocguid );\r
115 \r
116 static BOOLEAN\r
117 __sid_valid(\r
118         IN              vnic_adapter_t          *p_adapter,\r
119         IN              ib_net64_t                      sid );\r
120 \r
121 static void\r
122 __adapter_cleanup(\r
123         IN      vnic_adapter_t          *p_adapter );\r
124 \r
125 #if ( LBFO_ENABLED )\r
126 \r
127 static NDIS_STATUS\r
128 __adapter_set_failover_primary(\r
129          IN             vnic_adapter_t*  const p_adapter,\r
130          IN             BOOLEAN                 promote_secondary );\r
131 \r
132 static NDIS_STATUS\r
133 __adapter_set_failover_secondary(\r
134          IN             vnic_adapter_t* const   p_adapter,\r
135          IN             NDIS_HANDLE                             primary_handle );\r
136 \r
137 static void\r
138 __adapter_add_to_failover_list(\r
139          IN             vnic_adapter_t* const   p_adapter,\r
140          IN             lbfo_state_t            failover_state );\r
141 static void\r
142 __adapter_remove_from_failover_list(\r
143          IN             vnic_adapter_t* const   p_adapter );\r
144 \r
145 static\r
146 vnic_adapter_t*\r
147 __adapter_find_on_failover_list(\r
148         IN              int                             list_flag,\r
149         IN              uint32_t                bundle_id );\r
150 \r
151 #endif // LBFO_ENABLED\r
152 \r
153 ib_api_status_t\r
154 vnic_create_adapter(\r
155         IN              NDIS_HANDLE                     h_handle,\r
156         IN              NDIS_HANDLE                     wrapper_config_context,\r
157         OUT             vnic_adapter_t**        const pp_adapter)\r
158 {\r
159         NDIS_STATUS                     status;\r
160         ib_api_status_t         ib_status;\r
161         vnic_adapter_t          *p_adapter;\r
162 \r
163         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
164 \r
165         status = NdisAllocateMemoryWithTag( &p_adapter, sizeof(vnic_adapter_t), 'pada');\r
166 \r
167         if ( status != NDIS_STATUS_SUCCESS )\r
168         {\r
169                 VNIC_TRACE_EXIT(VNIC_DBG_ERROR,("Failed to allocate adapter\n"));\r
170                 return IB_INSUFFICIENT_MEMORY;\r
171         }\r
172 \r
173         NdisZeroMemory( p_adapter, sizeof(vnic_adapter_t) );\r
174 \r
175         NdisAllocateSpinLock( &p_adapter->lock );\r
176         NdisAllocateSpinLock( &p_adapter->path_records_lock );\r
177         NdisAllocateSpinLock( &p_adapter->pending_list_lock );\r
178         NdisAllocateSpinLock( &p_adapter->cancel_list_lock );\r
179         \r
180         InitializeListHead( &p_adapter->send_pending_list );\r
181         InitializeListHead( &p_adapter->cancel_send_list );\r
182 \r
183         cl_qlist_init( &p_adapter->path_records_list );\r
184 \r
185         status = \r
186                 vnic_get_adapter_params( wrapper_config_context, &p_adapter->params );\r
187 \r
188         if ( status != NDIS_STATUS_SUCCESS )\r
189         {\r
190                 VNIC_TRACE( VNIC_DBG_ERROR,\r
191                         (" vnic_get_adapter_params failed with status %d\n", status));\r
192                 NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
193                 return IB_INVALID_PARAMETER;\r
194         }\r
195 \r
196         status = vnic_get_adapter_interface( h_handle, p_adapter );\r
197         if ( status != NDIS_STATUS_SUCCESS )\r
198         {\r
199                 VNIC_TRACE( VNIC_DBG_ERROR,\r
200                         ("failed status %x\n", status ) );\r
201                 NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
202                 return IB_INVALID_PARAMETER;\r
203         }\r
204 \r
205         /*Open AL */\r
206         ib_status = p_adapter->ifc.open_al( &p_adapter->h_al );\r
207         if ( ib_status != IB_SUCCESS )\r
208         {\r
209                 VNIC_TRACE( VNIC_DBG_ERROR,\r
210                         ("ib_open_al returned %s\n", \r
211                                 p_adapter->ifc.get_err_str( ib_status )) );\r
212                 NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
213                 return ib_status;\r
214         }\r
215 \r
216         /* we will use these indexes later as an viport instance ID for connect request\r
217         *  since target requires unique instance per connection per IOC.\r
218         */\r
219         p_adapter->primaryPath.instance = NETPATH_PRIMARY;\r
220         p_adapter->secondaryPath.instance = NETPATH_SECONDARY;\r
221         \r
222         /* set adapter level params here */\r
223         p_adapter->vlan_info = p_adapter->params.VlanInfo;\r
224 \r
225 #if ( LBFO_ENABLED )\r
226 \r
227         p_adapter->failover.bundle_id = p_adapter->params.bundle_id;\r
228         p_adapter->failover.fo_state = _ADAPTER_NOT_BUNDLED;\r
229 \r
230 #endif\r
231 \r
232         p_adapter->h_handle = h_handle;\r
233         *pp_adapter = p_adapter;\r
234 \r
235         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
236         return IB_SUCCESS;\r
237 }\r
238 \r
239 \r
240 void\r
241 vnic_destroy_adapter(\r
242          IN      vnic_adapter_t         *p_adapter)\r
243 {\r
244         ib_api_status_t ib_status = IB_SUCCESS;\r
245         ib_pnp_handle_t  h_pnp;\r
246         ib_al_handle_t   h_al;\r
247 \r
248         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
249 \r
250         ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
251 \r
252         if( ( h_pnp = InterlockedExchangePointer( (void *)&p_adapter->h_pnp, NULL ) ) != NULL )\r
253         {\r
254                 ib_status =\r
255                         p_adapter->ifc.dereg_pnp( h_pnp, NULL );\r
256         }\r
257 \r
258                 /* should not receive new path notifications anymore, safe to cleanup */\r
259 \r
260         if( InterlockedCompareExchange( (volatile LONG *)&p_adapter->state,\r
261                                 INIC_DEREGISTERING, INIC_REGISTERED ) == INIC_REGISTERED )\r
262         {\r
263                 __adapter_cleanup( p_adapter );\r
264         }\r
265 \r
266         _adapter_close_ca( p_adapter );\r
267 \r
268 #if ( LBFO_ENABLED )\r
269 \r
270         __adapter_remove_from_failover_list( p_adapter );\r
271 \r
272 #endif\r
273 \r
274         InterlockedExchange( (volatile LONG *)&p_adapter->state, INIC_UNINITIALIZED );\r
275         if( ( h_al = InterlockedExchangePointer( (void *)&p_adapter->h_al, NULL ) ) != NULL )\r
276         {\r
277                 ib_status = p_adapter->ifc.close_al( h_al );\r
278                 ASSERT( ib_status == IB_SUCCESS );\r
279         }\r
280 \r
281         NdisFreeSpinLock( &p_adapter->lock );\r
282         NdisFreeSpinLock( &p_adapter->path_records_lock );\r
283         NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
284         p_adapter = NULL;\r
285 \r
286         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
287 }\r
288 \r
289 static ib_api_status_t\r
290 _adapter_open_ca(\r
291                 IN              vnic_adapter_t* const   p_adapter )\r
292 {\r
293         ib_api_status_t         ib_status = IB_SUCCESS;\r
294         ib_al_ifc_t                     *p_ifc  = &p_adapter->ifc;\r
295         uint32_t                        attr_size;\r
296         ib_ca_attr_t            *p_ca_attrs;\r
297         uint32_t                        num;\r
298         uint64_t        start_addr      = 0;\r
299         \r
300         if( p_adapter->h_ca )\r
301                 return ib_status;\r
302 \r
303         ib_status = p_ifc->open_ca( p_adapter->h_al,\r
304                                                                 p_adapter->ifc_data.ca_guid,\r
305                                                                 NULL, //ib_asyncEvent,\r
306                                                                 p_adapter,\r
307                                                                 &p_adapter->h_ca );\r
308 \r
309         if ( ib_status != IB_SUCCESS )\r
310         {\r
311                 VNIC_TRACE( VNIC_DBG_ERROR,\r
312                         ("Failed to open hca\n") );\r
313                 return IB_INSUFFICIENT_RESOURCES;\r
314         }\r
315 \r
316         ib_status = p_ifc->query_ca( p_adapter->h_ca, NULL , &attr_size );\r
317         if( ib_status != IB_INSUFFICIENT_MEMORY )\r
318         {\r
319                 VNIC_TRACE( VNIC_DBG_ERROR,\r
320                         ("ib_query_ca failed status %s\n",\r
321                         p_ifc->get_err_str( ib_status )) );\r
322                 \r
323                 ib_status = IB_INSUFFICIENT_RESOURCES;\r
324                 goto ca_failure;\r
325         }\r
326 \r
327         ASSERT( attr_size );\r
328 \r
329         p_ca_attrs = cl_zalloc( attr_size );\r
330         if ( p_ca_attrs == NULL )\r
331         {\r
332                 VNIC_TRACE( VNIC_DBG_ERROR,\r
333                         ("Allocate %d bytes failed for Channel adapter\n", attr_size ));\r
334 \r
335                 ib_status = IB_INSUFFICIENT_MEMORY;\r
336                 goto ca_failure;\r
337         }\r
338 \r
339         ib_status = p_ifc->query_ca( p_adapter->h_ca, p_ca_attrs , &attr_size );\r
340         if ( ib_status != IB_SUCCESS )\r
341         {\r
342                 VNIC_TRACE( VNIC_DBG_ERROR,\r
343                         ("CA attributes query failed\n") );\r
344                 cl_free ( p_ca_attrs );\r
345                 goto ca_failure;\r
346         }\r
347 \r
348         p_adapter->ca.numPorts = p_ca_attrs->num_ports;\r
349         if( p_adapter->ca.numPorts > VNIC_CA_MAX_PORTS )\r
350                 p_adapter->ca.numPorts = VNIC_CA_MAX_PORTS;\r
351 \r
352         for( num = 0; num < p_adapter->ca.numPorts; num++ )\r
353                 p_adapter->ca.portGuids[num] = p_ca_attrs->p_port_attr[num].port_guid;\r
354 \r
355         p_adapter->ca.caGuid = p_adapter->ifc_data.ca_guid;\r
356 \r
357         cl_free ( p_ca_attrs );\r
358 \r
359         ib_status = p_adapter->ifc.alloc_pd( p_adapter->h_ca,\r
360                 IB_PDT_NORMAL, p_adapter, &p_adapter->ca.hPd );\r
361         if ( ib_status != IB_SUCCESS )\r
362         {\r
363                 VNIC_TRACE_EXIT ( VNIC_DBG_ERROR,\r
364                         ("Alloc PD failed status %s(%d)\n",\r
365                         p_adapter->ifc.get_err_str(ib_status), ib_status ));\r
366                 goto ca_failure;\r
367         }\r
368 \r
369         if ( ( ib_status = ibregion_physInit( p_adapter,\r
370                                                          &p_adapter->ca.region,\r
371                                                          p_adapter->ca.hPd,\r
372                                                          &start_addr,\r
373                                                          MAX_PHYS_MEMORY ) ) != IB_SUCCESS )\r
374         {\r
375                 VNIC_TRACE_EXIT ( VNIC_DBG_ERROR,\r
376                         ("phys region init failed status %s(%d)\n",\r
377                         p_adapter->ifc.get_err_str(ib_status), ib_status ));\r
378                 p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL );\r
379                 goto ca_failure;\r
380         }\r
381 \r
382         return ib_status;\r
383 \r
384 ca_failure:\r
385         if( p_adapter->h_ca )\r
386                 p_ifc->close_ca( p_adapter->h_ca, NULL );\r
387 \r
388         return ib_status;\r
389 }\r
390 \r
391 static BOOLEAN\r
392 _adapter_params_sanity_check(vnic_params_t *p_params)\r
393 {\r
394         DEFAULT_PARAM( p_params->MaxAddressEntries, MAX_ADDRESS_ENTRIES );\r
395         DEFAULT_PARAM( p_params->MinAddressEntries, MIN_ADDRESS_ENTRIES );\r
396 \r
397         DEFAULT_PARAM( p_params->ViportStatsInterval, VIPORT_STATS_INTERVAL );\r
398         DEFAULT_PARAM( p_params->ViportHbInterval, VIPORT_HEARTBEAT_INTERVAL );\r
399         DEFAULT_PARAM( p_params->ViportHbTimeout, VIPORT_HEARTBEAT_TIMEOUT );\r
400 \r
401         DEFAULT_PARAM( p_params->ControlRspTimeout, CONTROL_RSP_TIMEOUT );\r
402         DEFAULT_PARAM( p_params->ControlReqRetryCount, CONTROL_REQ_RETRY_COUNT );\r
403 \r
404         DEFAULT_PARAM( p_params->RetryCount, RETRY_COUNT );\r
405         DEFAULT_PARAM( p_params->MinRnrTimer, MIN_RNR_TIMER );\r
406 \r
407         DEFAULT_PARAM( p_params->MaxViportsPerNetpath, MAX_VIPORTS_PER_NETPATH );\r
408         DEFAULT_PARAM( p_params->DefaultViportsPerNetpath, DEFAULT_VIPORTS_PER_NETPATH );\r
409 \r
410         DEFAULT_PARAM( p_params->DefaultPkey, DEFAULT_PKEY );\r
411         DEFAULT_PARAM( p_params->NotifyBundleSz, NOTIFY_BUNDLE_SZ );\r
412         DEFAULT_PARAM( p_params->DefaultNoPathTimeout, DEFAULT_NO_PATH_TIMEOUT );\r
413         DEFAULT_PARAM( p_params->DefaultPrimaryConnectTimeout, DEFAULT_PRI_CON_TIMEOUT );\r
414         DEFAULT_PARAM( p_params->DefaultPrimaryReconnectTimeout, DEFAULT_PRI_RECON_TIMEOUT );\r
415         DEFAULT_PARAM( p_params->DefaultPrimarySwitchTimeout, DEFAULT_PRI_SWITCH_TIMEOUT );\r
416         DEFAULT_PARAM( p_params->DefaultPreferPrimary, DEFAULT_PREFER_PRIMARY );\r
417 \r
418         U32_RANGE( p_params->MaxAddressEntries );\r
419         U32_RANGE( p_params->MinAddressEntries );\r
420         RANGE_CHECK( p_params->MinMtu, MIN_MTU, MAX_MTU );\r
421         RANGE_CHECK( p_params->MaxMtu, MIN_MTU, MAX_MTU );\r
422         U32_RANGE( p_params->HostRecvPoolEntries );\r
423         U32_RANGE( p_params->MinHostPoolSz );\r
424         U32_RANGE( p_params->MinEiocPoolSz );\r
425         U32_RANGE( p_params->MaxEiocPoolSz );\r
426         U32_ZERO_RANGE( p_params->MinHostKickTimeout );\r
427         U32_ZERO_RANGE( p_params->MaxHostKickTimeout );\r
428         U32_ZERO_RANGE( p_params->MinHostKickEntries );\r
429         U32_ZERO_RANGE( p_params->MaxHostKickEntries );\r
430         U32_ZERO_RANGE( p_params->MinHostKickBytes );\r
431         U32_ZERO_RANGE( p_params->MaxHostKickBytes );\r
432         U32_RANGE( p_params->MinHostUpdateSz );\r
433         U32_RANGE( p_params->MaxHostUpdateSz );\r
434         U32_RANGE( p_params->MinEiocUpdateSz );\r
435         U32_RANGE( p_params->MaxEiocUpdateSz );\r
436         U8_RANGE( p_params->NotifyBundleSz );\r
437         U32_ZERO_RANGE( p_params->ViportStatsInterval );\r
438         U32_ZERO_RANGE( p_params->ViportHbInterval );\r
439         U32_ZERO_RANGE( p_params->ViportHbTimeout );\r
440         U32_RANGE( p_params->ControlRspTimeout );\r
441         U8_RANGE( p_params->ControlReqRetryCount );\r
442         ZERO_RANGE_CHECK( p_params->RetryCount, 0, 7 );\r
443         ZERO_RANGE_CHECK( p_params->MinRnrTimer, 0, 31 );\r
444         U32_RANGE( p_params->DefaultViportsPerNetpath );\r
445         U8_RANGE( p_params->MaxViportsPerNetpath );\r
446         U16_ZERO_RANGE( p_params->DefaultPkey );\r
447         U32_RANGE( p_params->DefaultNoPathTimeout );\r
448         U32_RANGE( p_params->DefaultPrimaryConnectTimeout );\r
449         U32_RANGE( p_params->DefaultPrimaryReconnectTimeout );\r
450         U32_RANGE( p_params->DefaultPrimarySwitchTimeout );\r
451         BOOLEAN_RANGE( p_params->DefaultPreferPrimary );\r
452         BOOLEAN_RANGE( p_params->UseRxCsum );\r
453         BOOLEAN_RANGE( p_params->UseTxCsum );\r
454 \r
455         LESS_THAN_OR_EQUAL( p_params->MinAddressEntries, p_params->MaxAddressEntries );\r
456         LESS_THAN_OR_EQUAL( p_params->MinMtu, p_params->MaxMtu );\r
457         LESS_THAN_OR_EQUAL( p_params->MinHostPoolSz, p_params->HostRecvPoolEntries );\r
458         POWER_OF_2( p_params->HostRecvPoolEntries );\r
459         POWER_OF_2( p_params->MinHostPoolSz );\r
460         POWER_OF_2( p_params->NotifyBundleSz );\r
461         LESS_THAN( p_params->NotifyBundleSz, p_params->MinEiocPoolSz );\r
462         LESS_THAN_OR_EQUAL( p_params->MinEiocPoolSz, p_params->MaxEiocPoolSz );\r
463         POWER_OF_2( p_params->MinEiocPoolSz );\r
464         POWER_OF_2( p_params->MaxEiocPoolSz );\r
465         LESS_THAN_OR_EQUAL( p_params->MinHostKickTimeout, p_params->MaxHostKickTimeout );\r
466         LESS_THAN_OR_EQUAL( p_params->MinHostKickEntries, p_params->MaxHostKickEntries );\r
467         LESS_THAN_OR_EQUAL( p_params->MinHostKickBytes, p_params->MaxHostKickBytes );\r
468         LESS_THAN_OR_EQUAL( p_params->MinHostUpdateSz, p_params->MaxHostUpdateSz );\r
469         POWER_OF_2( p_params->MinHostUpdateSz );\r
470         POWER_OF_2( p_params->MaxHostUpdateSz );\r
471         LESS_THAN( p_params->MinHostUpdateSz, p_params->MinHostPoolSz );\r
472         LESS_THAN( p_params->MaxHostUpdateSz, p_params->HostRecvPoolEntries );\r
473         LESS_THAN_OR_EQUAL( p_params->MinEiocUpdateSz, p_params->MaxEiocUpdateSz );\r
474         POWER_OF_2( p_params->MinEiocUpdateSz );\r
475         POWER_OF_2( p_params->MaxEiocUpdateSz );\r
476         LESS_THAN( p_params->MinEiocUpdateSz, p_params->MinEiocPoolSz );\r
477         LESS_THAN( p_params->MaxEiocUpdateSz, p_params->MaxEiocPoolSz );\r
478         LESS_THAN_OR_EQUAL( p_params->DefaultViportsPerNetpath, p_params->MaxViportsPerNetpath );\r
479 \r
480         return TRUE;\r
481 \r
482 }\r
483 NDIS_STATUS\r
484 vnic_get_adapter_params(\r
485         IN                      NDIS_HANDLE                             wrapper_config_context,\r
486         OUT                     vnic_params_t* const    p_params )\r
487 {\r
488         NDIS_STATUS                                             status;\r
489         NDIS_HANDLE                                             h_config;\r
490         NDIS_CONFIGURATION_PARAMETER    *p_reg_prm;\r
491         NDIS_STRING                                             keyword;\r
492 \r
493         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
494 \r
495         CL_ASSERT(p_params );\r
496 \r
497         /* prepare params for default initialization */\r
498         cl_memset( p_params, 0xff, sizeof (vnic_params_t) );\r
499 \r
500         NdisOpenConfiguration( &status, &h_config, wrapper_config_context );\r
501         if( status != NDIS_STATUS_SUCCESS )\r
502         {\r
503                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
504                         ("NdisOpenConfiguration returned 0x%.8x\n", status) );\r
505                 return status;\r
506         }\r
507 \r
508         status = NDIS_STATUS_FAILURE;\r
509         p_reg_prm = NULL;\r
510 \r
511         RtlInitUnicodeString( &keyword, L"PayloadMtu" );\r
512         NdisReadConfiguration(\r
513                 &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
514 \r
515         p_params->MinMtu = ( status != NDIS_STATUS_SUCCESS ) ? MIN_MTU:\r
516                                                 p_reg_prm->ParameterData.IntegerData;\r
517         p_params->MaxMtu = MAX_MTU;\r
518 \r
519         RtlInitUnicodeString( &keyword, L"UseRxCsum" );\r
520         NdisReadConfiguration(\r
521                 &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
522 \r
523         p_params->UseRxCsum = ( status != NDIS_STATUS_SUCCESS ) ?\r
524                 TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE;\r
525 \r
526         RtlInitUnicodeString( &keyword, L"UseTxCsum" );\r
527         NdisReadConfiguration(\r
528                 &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
529 \r
530         /* turn it on by default, if not present */\r
531         p_params->UseTxCsum = ( status != NDIS_STATUS_SUCCESS ) ?\r
532                 TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE;\r
533         \r
534         /* handle VLAN + Priority paramters */\r
535         RtlInitUnicodeString( &keyword, L"VlanId" );\r
536         NdisReadConfiguration(\r
537                 &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
538 \r
539         if( status == NDIS_STATUS_SUCCESS )\r
540         {\r
541                 p_params->VlanInfo = \r
542                         ( p_reg_prm->ParameterData.IntegerData & 0x00000fff );\r
543 \r
544                 RtlInitUnicodeString( &keyword, L"UserPriority" );\r
545                 NdisReadConfiguration(\r
546                         &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
547         \r
548                 p_params->VlanInfo |= ( status != NDIS_STATUS_SUCCESS ) ? 0 :\r
549                 ( ( p_reg_prm->ParameterData.IntegerData & 0x00000007 ) << 13 );\r
550         }\r
551         else\r
552         {\r
553                 p_params->VlanInfo = 0;\r
554         }\r
555 \r
556         RtlInitUnicodeString( &keyword, L"SecondaryPath" );\r
557         NdisReadConfiguration(\r
558                 &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
559 \r
560         /* disable, if not set. Save extra viport slot */\r
561         p_params->SecondaryPath = ( status != NDIS_STATUS_SUCCESS ) ?\r
562                 FALSE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE;\r
563 \r
564         RtlInitUnicodeString( &keyword, L"Heartbeat" );\r
565         NdisReadConfiguration(\r
566                 &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
567 \r
568         p_params->ViportHbInterval = ( status != NDIS_STATUS_SUCCESS ) ?\r
569                 VIPORT_HEARTBEAT_INTERVAL : p_reg_prm->ParameterData.IntegerData;\r
570 \r
571 #if ( LBFO_ENABLED )\r
572         /* read Failover group Name/Number */\r
573 \r
574         RtlInitUnicodeString( &keyword, L"BundleId" );\r
575         NdisReadConfiguration(\r
576                 &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
577         \r
578         p_params->bundle_id = ( status != NDIS_STATUS_SUCCESS ) ? 0 :\r
579         p_reg_prm->ParameterData.IntegerData;\r
580 #endif // LBFO_ENABLED\r
581 \r
582         NdisCloseConfiguration( h_config );\r
583         \r
584         /* initialize the rest of  adapter parameters with driver's global set */\r
585         if( g_vnic.p_params != NULL )\r
586         {\r
587                 /* get global parameters from service entry */\r
588                 p_params->MinHostPoolSz = g_vnic.p_params[INDEX_MIN_HOST_POOL_SZ].value;\r
589                 p_params->HostRecvPoolEntries = g_vnic.p_params[INDEX_HOST_RECV_POOL_ENTRIES].value;\r
590 \r
591                 p_params->MinEiocPoolSz = g_vnic.p_params[INDEX_MIN_EIOC_POOL_SZ].value;\r
592                 p_params->MaxEiocPoolSz = g_vnic.p_params[INDEX_MAX_EIOC_POOL_SZ].value;\r
593 \r
594                 p_params->MinHostKickTimeout = g_vnic.p_params[INDEX_MIN_HOST_KICK_TIMEOUT].value;\r
595                 p_params->MaxHostKickTimeout = g_vnic.p_params[INDEX_MAX_HOST_KICK_TIMEOUT].value;\r
596 \r
597                 p_params->MinHostKickEntries = g_vnic.p_params[INDEX_MIN_HOST_KICK_ENTRIES].value;\r
598                 p_params->MaxHostKickEntries = g_vnic.p_params[INDEX_MAX_HOST_KICK_ENTRIES].value;\r
599 \r
600                 p_params->MinHostKickBytes = g_vnic.p_params[INDEX_MIN_HOST_KICK_BYTES].value;\r
601                 p_params->MaxHostKickBytes = g_vnic.p_params[INDEX_MAX_HOST_KICK_BYTES].value;\r
602         \r
603                 p_params->MinHostUpdateSz = g_vnic.p_params[INDEX_MIN_HOST_UPDATE_SZ].value;\r
604                 p_params->MaxHostUpdateSz = g_vnic.p_params[INDEX_MAX_HOST_UPDATE_SZ].value;\r
605 \r
606                 p_params->MinEiocUpdateSz = g_vnic.p_params[INDEX_MIN_EIOC_UPDATE_SZ].value;\r
607                 p_params->MaxEiocUpdateSz = g_vnic.p_params[INDEX_MAX_EIOC_UPDATE_SZ].value;\r
608                 \r
609                 p_params->ViportHbTimeout = g_vnic.p_params[INDEX_HEARTBEAT_TIMEOUT].value;\r
610         }\r
611         else\r
612         {\r
613                 /* set default constants */\r
614                 p_params->MinHostPoolSz = MIN_HOST_POOL_SZ;\r
615                 p_params->HostRecvPoolEntries = HOST_RECV_POOL_ENTRIES;\r
616                 p_params->MinEiocPoolSz = MIN_EIOC_POOL_SZ;\r
617                 p_params->MaxEiocPoolSz = MAX_EIOC_POOL_SZ;\r
618                 p_params->MinHostKickTimeout = MIN_HOST_KICK_TIMEOUT;\r
619                 p_params->MaxHostKickTimeout = MAX_HOST_KICK_TIMEOUT;\r
620                 p_params->MinHostKickEntries = MIN_HOST_KICK_ENTRIES;\r
621                 p_params->MaxHostKickEntries = MAX_HOST_KICK_ENTRIES;\r
622                 p_params->MinHostKickBytes = MIN_HOST_KICK_BYTES;\r
623                 p_params->MaxHostKickBytes = MAX_HOST_KICK_BYTES;\r
624                 p_params->MinHostUpdateSz = MIN_HOST_UPDATE_SZ;\r
625                 p_params->MaxHostUpdateSz = MAX_HOST_UPDATE_SZ;\r
626                 p_params->MinEiocUpdateSz = MIN_EIOC_UPDATE_SZ;\r
627                 p_params->MaxEiocUpdateSz = MAX_EIOC_UPDATE_SZ;\r
628         }\r
629 \r
630         status = ( _adapter_params_sanity_check(p_params)?\r
631                                 NDIS_STATUS_SUCCESS: NDIS_STATUS_FAILURE );\r
632 \r
633         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
634         return status;\r
635 }\r
636 \r
637 ib_api_status_t\r
638 adapter_viport_allocate(\r
639         IN                      vnic_adapter_t* const           p_adapter,\r
640         IN OUT          viport_t**              const           pp_viport )\r
641 {\r
642         viport_t        *p_viport;\r
643         NDIS_STATUS      status;\r
644 \r
645         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
646 \r
647         NdisAcquireSpinLock( &p_adapter->lock );\r
648 \r
649         status = NdisAllocateMemoryWithTag( &p_viport, sizeof(viport_t), 'trop' );\r
650         if( status != NDIS_STATUS_SUCCESS )\r
651         {\r
652                 NdisReleaseSpinLock( &p_adapter->lock );\r
653                 VNIC_TRACE_EXIT(VNIC_DBG_ERROR,\r
654                                 ( "Failed allocating Viport structure\n" ));\r
655                 return IB_ERROR;\r
656         }\r
657 \r
658         NdisZeroMemory( p_viport, sizeof(viport_t) );\r
659         NdisAllocateSpinLock( &p_viport->lock );\r
660         InitializeListHead( &p_viport->listPtrs );\r
661         cl_event_init( &p_viport->sync_event, FALSE );\r
662         \r
663         p_viport->p_adapter = p_adapter;\r
664         viport_config_defaults ( p_viport );\r
665 \r
666         control_construct( &p_viport->control, p_viport );\r
667         data_construct( &p_viport->data, p_viport );\r
668 \r
669         p_viport->ioc_num = _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid );\r
670         if( !p_adapter->ioc_num )\r
671         {\r
672                 p_adapter->ioc_num = p_viport->ioc_num;\r
673         }\r
674 \r
675         CL_ASSERT( p_adapter->ioc_num == p_viport->ioc_num );\r
676         \r
677         *pp_viport = p_viport;\r
678 \r
679         NdisReleaseSpinLock( &p_adapter->lock );\r
680 \r
681         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
682         return IB_SUCCESS;\r
683 }\r
684 \r
685 \r
686 static void\r
687 _adapter_netpath_free(\r
688         IN              vnic_adapter_t* const   p_adapter,\r
689         IN              Netpath_t*                              p_netpath )\r
690 {\r
691 \r
692         UNREFERENCED_PARAMETER( p_adapter );\r
693 \r
694         if( netpath_is_valid( p_netpath ) )\r
695         {\r
696                 VNIC_TRACE( VNIC_DBG_INFO,\r
697                                         ("IOC[%d] instance %d Free Path\n",\r
698                                         p_adapter->ioc_num, p_netpath->instance ));\r
699 \r
700                 netpath_free( p_netpath );\r
701                 netpath_init( p_netpath, NULL );\r
702         }\r
703 }\r
704 \r
705 NDIS_STATUS\r
706 adapter_set_mcast(\r
707         IN                              vnic_adapter_t* const           p_adapter,\r
708         IN                              mac_addr_t* const                       p_mac_array,\r
709         IN              const   uint8_t                                         mc_count )\r
710 {\r
711         NDIS_STATUS     status;\r
712         int i;\r
713         VNIC_ENTER( VNIC_DBG_MCAST );\r
714 \r
715         if( !netpath_is_valid( p_adapter->p_currentPath ) )\r
716                 return NDIS_STATUS_NOT_ACCEPTED;\r
717 \r
718         VNIC_TRACE( VNIC_DBG_MCAST,\r
719                 ("IOC[%d] MCAST COUNT to set = %d\n", \r
720                                                 p_adapter->ioc_num, mc_count));\r
721 \r
722         /* Copy the MC address list into the adapter. */\r
723         if( mc_count )\r
724         {\r
725                 RtlCopyMemory(\r
726                         p_adapter->mcast_array, p_mac_array, mc_count * MAC_ADDR_LEN );\r
727                 for( i = 0; i < mc_count; i++ )\r
728                 VNIC_TRACE( VNIC_DBG_MCAST,\r
729                         ("[%d] %02x:%02x:%02x:%02x:%02x:%02x\n", i,\r
730                         p_mac_array->addr[0], p_mac_array->addr[1],     p_mac_array->addr[2],\r
731                         p_mac_array->addr[3], p_mac_array->addr[4],     p_mac_array->addr[5] ));\r
732         }\r
733         p_adapter->mc_count = mc_count;\r
734 \r
735         p_adapter->pending_set = TRUE;\r
736         status = netpath_setMulticast( p_adapter->p_currentPath );\r
737         if( status != NDIS_STATUS_PENDING )\r
738         {\r
739                 p_adapter->pending_set = FALSE;\r
740         }\r
741 \r
742         VNIC_EXIT( VNIC_DBG_MCAST );\r
743         return status;\r
744 }\r
745 \r
746 \r
747 static BOOLEAN\r
748 __path_records_match(\r
749         IN                      ib_path_rec_t* const    p_path1,\r
750         IN                      ib_path_rec_t* const    p_path2 )\r
751 {\r
752         if( p_path1->dgid.unicast.prefix != p_path2->dgid.unicast.prefix )\r
753                 return FALSE;\r
754         if( p_path1->dgid.unicast.interface_id != p_path2->dgid.unicast.interface_id )\r
755                 return FALSE;\r
756         if( p_path1->dlid != p_path2->dlid )\r
757                 return FALSE;\r
758 \r
759         if( p_path1->sgid.unicast.prefix != p_path2->sgid.unicast.prefix )\r
760                 return FALSE;\r
761         if( p_path1->sgid.unicast.interface_id != p_path2->sgid.unicast.interface_id )\r
762                 return FALSE;\r
763         if( p_path1->slid != p_path2->slid )\r
764                 return FALSE;\r
765 \r
766         if( p_path1->pkey != p_path2->pkey )\r
767                 return FALSE;\r
768         if( p_path1->rate != p_path2->rate )\r
769                 return FALSE;\r
770         if( ib_path_rec_sl(p_path1) != ib_path_rec_sl(p_path2) )\r
771                 return FALSE;\r
772         if( p_path1->tclass != p_path2->tclass )\r
773                 return FALSE;\r
774 \r
775         return TRUE;\r
776 }\r
777 \r
778 static BOOLEAN\r
779 __sid_valid(\r
780                 IN              vnic_adapter_t          *p_adapter,\r
781                 IN              ib_net64_t                      sid )\r
782 {\r
783         vnic_sid_t      svc_id;\r
784         svc_id.as_uint64 = sid;\r
785         if( ( svc_id.s.base_id & 0x10 ) != 0x10 )\r
786                 return FALSE;\r
787         if( svc_id.s.oui[0] != 0x00 &&\r
788                 svc_id.s.oui[1] != 0x06 &&\r
789                 svc_id.s.oui[2] != 0x6a )\r
790                 return FALSE;\r
791         if ( svc_id.s.type != CONTROL_SID &&\r
792                  svc_id.s.type != DATA_SID )\r
793                  return FALSE;\r
794         if ( svc_id.s.ioc_num   != _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ) )\r
795                 return FALSE;\r
796         return TRUE;\r
797 }\r
798 static inline uint8_t\r
799 _get_ioc_num_from_iocguid(\r
800                   IN ib_net64_t         *p_iocguid )\r
801 {\r
802         return ( (vnic_ioc_guid_t *)p_iocguid)->s.ioc_num;\r
803 }\r
804 \r
805 static\r
806 vnic_path_record_t*\r
807 __path_record_add(\r
808         IN                              vnic_adapter_t* const   p_adapter,\r
809         IN                              ib_path_rec_t* const    p_path_rec )\r
810 {\r
811 \r
812         vnic_path_record_t              *p_path;\r
813 \r
814         p_path = __path_record_find( p_adapter, p_path_rec );\r
815 \r
816         if( !p_path )\r
817         {\r
818                 p_path = cl_zalloc( sizeof( vnic_path_record_t ) );\r
819                 if( !p_path )\r
820                         return NULL;\r
821 \r
822                 NdisAcquireSpinLock( &p_adapter->path_records_lock );\r
823                 \r
824                 p_path->path_rec = *p_path_rec;\r
825                 cl_qlist_insert_tail( &p_adapter->path_records_list, &p_path->list_entry );\r
826 \r
827                 NdisReleaseSpinLock( &p_adapter->path_records_lock );\r
828 \r
829                 VNIC_TRACE( VNIC_DBG_PNP,\r
830                         ("New path Added to the list[ list size %d]\n", \r
831                                 cl_qlist_count(&p_adapter->path_records_list) ));\r
832                 \r
833                 return p_path;\r
834         }\r
835         VNIC_TRACE( VNIC_DBG_PNP,\r
836                         ( "Path to add is already on the List\n" ) );\r
837 \r
838         return NULL;\r
839 }\r
840 \r
841 static\r
842 vnic_path_record_t*\r
843 __path_record_get(\r
844         IN                              vnic_adapter_t* const   p_adapter )\r
845 {\r
846         cl_list_item_t          *p_item;\r
847 \r
848         p_item = cl_qlist_head( &p_adapter->path_records_list );\r
849 \r
850         if( p_item != cl_qlist_end( &p_adapter->path_records_list ) )\r
851         {\r
852                 return ( vnic_path_record_t *)p_item;\r
853         }\r
854         return NULL;\r
855 }\r
856 \r
857 static \r
858 vnic_path_record_t*\r
859 __path_record_remove(\r
860                 IN                      vnic_adapter_t* const   p_adapter,\r
861                 IN                      ib_path_rec_t* const    p_path_rec )\r
862 {\r
863 \r
864         vnic_path_record_t      *p_path;\r
865 \r
866 \r
867         p_path = __path_record_find( p_adapter, p_path_rec );\r
868 \r
869         if ( p_path )\r
870         {\r
871                 NdisAcquireSpinLock( &p_adapter->path_records_lock );\r
872 \r
873                 cl_qlist_remove_item( &p_adapter->path_records_list, &p_path->list_entry );\r
874 \r
875                 NdisReleaseSpinLock( &p_adapter->path_records_lock );\r
876         }\r
877         \r
878         return p_path;\r
879 }\r
880 \r
881 static\r
882 vnic_path_record_t *\r
883 __path_record_find( \r
884         IN              vnic_adapter_t* const   p_adapter,\r
885         IN              ib_path_rec_t* const    p_path_rec )\r
886 {\r
887         cl_list_item_t          *p_item;\r
888         vnic_path_record_t      *p_path = NULL;\r
889 \r
890         NdisAcquireSpinLock( &p_adapter->path_records_lock );\r
891 \r
892         if( !cl_qlist_count( &p_adapter->path_records_list ) )\r
893         {\r
894                 NdisReleaseSpinLock( &p_adapter->path_records_lock );\r
895                 return NULL;\r
896         }\r
897         \r
898         p_item = cl_qlist_head( &p_adapter->path_records_list );\r
899 \r
900         while( p_item != cl_qlist_end( &p_adapter->path_records_list ) )\r
901         {\r
902                 p_path = ( vnic_path_record_t *)p_item;\r
903                 \r
904                 if ( __path_records_match( &p_path->path_rec, p_path_rec ) )\r
905                 {\r
906                         break;\r
907                 }\r
908 \r
909                 p_item = cl_qlist_next( p_item );\r
910         }\r
911 \r
912         NdisReleaseSpinLock( &p_adapter->path_records_lock );\r
913 \r
914         if( p_item == cl_qlist_end( &p_adapter->path_records_list ) )\r
915         {\r
916                 p_path = NULL;\r
917         }\r
918         return p_path;\r
919 }\r
920 \r
921 void\r
922 __pending_queue_cleanup( \r
923         IN              vnic_adapter_t  *p_adapter )\r
924 {\r
925         LIST_ENTRY              *p_list_item;\r
926         NDIS_PACKET             *p_packet;\r
927 \r
928         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
929 \r
930         /* clear pending queue if any */\r
931 \r
932         while( ( p_list_item = NdisInterlockedRemoveHeadList(\r
933                 &p_adapter->send_pending_list,\r
934                 &p_adapter->pending_list_lock )) != NULL )\r
935         {\r
936                 p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item );\r
937                 if ( p_packet )\r
938                 {\r
939                         NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_FAILURE );\r
940                         NdisMSendComplete( p_adapter->h_handle, p_packet, NDIS_STATUS_FAILURE );\r
941                 }\r
942         }\r
943 \r
944         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
945 }\r
946 \r
947 static void\r
948 __path_records_cleanup(\r
949                    vnic_adapter_t       *p_adapter )\r
950 {\r
951 \r
952         vnic_path_record_t      *p_path;\r
953         cl_list_item_t  *p_item;\r
954 \r
955         p_item = cl_qlist_remove_head( &p_adapter->path_records_list );\r
956 \r
957         while( p_item != cl_qlist_end( &p_adapter->path_records_list ) )\r
958         {\r
959                 p_path = (vnic_path_record_t *)p_item;\r
960 \r
961                 cl_free( p_path );\r
962 \r
963                 p_item = cl_qlist_remove_head( &p_adapter->path_records_list );\r
964         }\r
965         \r
966         return;\r
967 }\r
968 \r
969 ib_api_status_t\r
970 __vnic_pnp_cb(\r
971         IN              ib_pnp_rec_t                *p_pnp_rec )\r
972 {\r
973         ib_api_status_t                 ib_status = IB_SUCCESS;\r
974         ib_pnp_ioc_rec_t                *p_ioc_rec;\r
975         ib_pnp_ioc_path_rec_t   *p_ioc_path;\r
976         vnic_path_record_t              *p_path_record;\r
977         Netpath_t*                              p_netpath = NULL;\r
978 \r
979 #if ( LBFO_ENABLED )\r
980         vnic_adapter_t                  *p_primary_adapter;     \r
981 #endif\r
982 \r
983         vnic_adapter_t * p_adapter = (vnic_adapter_t *)p_pnp_rec->pnp_context;\r
984         \r
985         VNIC_ENTER( VNIC_DBG_PNP );\r
986 \r
987         CL_ASSERT( p_adapter );\r
988 \r
989         switch( p_pnp_rec->pnp_event )\r
990         {\r
991                 case IB_PNP_IOC_ADD:\r
992                         p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
993 \r
994                         if( p_adapter->ifc_data.ca_guid != p_ioc_rec->ca_guid )\r
995                         {\r
996                                 ib_status = IB_INVALID_GUID;\r
997                                 break;\r
998                         }\r
999                         if( p_adapter->ifc_data.guid != p_ioc_rec->info.profile.ioc_guid )\r
1000                         {\r
1001                                 ib_status = IB_INVALID_GUID;\r
1002                                 break;\r
1003                         }\r
1004                         InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_ADD );\r
1005 \r
1006                         VNIC_TRACE( VNIC_DBG_PNP, ("IB_PNP_IOC_ADD for %s.\n",\r
1007                                 p_ioc_rec->info.profile.id_string) );\r
1008 \r
1009                         /* get ioc profile data */\r
1010                         NdisAcquireSpinLock( &p_adapter->lock );\r
1011                 \r
1012                         if( !__sid_valid( p_adapter, p_ioc_rec->svc_entry_array[0].id ) )\r
1013                         {\r
1014                                 NdisReleaseSpinLock( &p_adapter->lock );\r
1015 \r
1016                                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
1017                                         ("Invalid Service ID %#I64x\n",p_ioc_rec->svc_entry_array[0].id ) );\r
1018 \r
1019                                 ib_status = IB_INVALID_GUID; // should it be set INVALID_SERVICE_TYPE ?\r
1020                                 break;\r
1021                         }\r
1022 \r
1023                         p_adapter->ioc_info = p_ioc_rec->info;\r
1024                         CL_ASSERT(p_adapter->ioc_info.profile.num_svc_entries == 2 );\r
1025                         \r
1026                         p_adapter->svc_entries[0] = p_ioc_rec->svc_entry_array[0];\r
1027                         p_adapter->svc_entries[1] = p_ioc_rec->svc_entry_array[1];\r
1028                         p_adapter->ioc_num = _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid );\r
1029 \r
1030                         VNIC_TRACE( VNIC_DBG_PNP,\r
1031                                 ("Found %d Service Entries.\n", p_adapter->ioc_info.profile.num_svc_entries));\r
1032 \r
1033                         NdisReleaseSpinLock( &p_adapter->lock );\r
1034                         \r
1035                         break;\r
1036 \r
1037                 case IB_PNP_IOC_REMOVE:\r
1038                         CL_ASSERT( p_pnp_rec->guid == p_adapter->ifc_data.guid );\r
1039                 \r
1040                         p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
1041 \r
1042                         if( InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE ) == IB_PNP_IOC_ADD )\r
1043                         {\r
1044                                 VNIC_TRACE( VNIC_DBG_INIT, ("IB_PNP_IOC_REMOVE for %s.\n",\r
1045                                                         p_adapter->ioc_info.profile.id_string) );\r
1046                         \r
1047                                 if( netpath_is_valid( p_adapter->p_currentPath ) )\r
1048                                 {\r
1049                                         netpath_stopXmit( p_adapter->p_currentPath );\r
1050                                         InterlockedExchange( &p_adapter->p_currentPath->carrier, (LONG)FALSE );\r
1051                                         netpath_linkDown( p_adapter->p_currentPath );\r
1052                                         __pending_queue_cleanup( p_adapter );\r
1053                                 }\r
1054                         }\r
1055                         break;\r
1056 \r
1057                 case IB_PNP_IOC_PATH_ADD:\r
1058                         /* path for our IOC ? */\r
1059                         if ( p_pnp_rec->guid != p_adapter->ifc_data.guid )\r
1060                         {\r
1061                                 VNIC_TRACE( VNIC_DBG_PNP,\r
1062                                         ("Getting path for wrong IOC\n") );\r
1063                                 ib_status = IB_INVALID_GUID;\r
1064                                 break;\r
1065                         }\r
1066                         p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
1067 \r
1068                         p_path_record = __path_record_add( p_adapter, &p_ioc_path->path );\r
1069                         if ( p_path_record == NULL )\r
1070                         {\r
1071                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1072                                         ("Failed to add path record\n") );\r
1073                                 break;\r
1074                         }\r
1075 \r
1076                         if( p_adapter->state == INIC_REGISTERED )\r
1077                         {\r
1078                                 if(     p_adapter->num_paths > 0 )\r
1079                                 {\r
1080                                         if( p_adapter->params.SecondaryPath != TRUE )\r
1081                                         {\r
1082                                                 VNIC_TRACE ( VNIC_DBG_WARN,\r
1083                                                 ("Allowed one path at a time\n") );\r
1084                                                 break;\r
1085                                         }\r
1086                                 }\r
1087 \r
1088                                 if( p_adapter->num_paths > 1 )\r
1089                                 {\r
1090                                         VNIC_TRACE ( VNIC_DBG_WARN,\r
1091                                         ("Max Paths[%d] Connected already\n", p_adapter->num_paths) );\r
1092                                         break;\r
1093                                 }\r
1094                         }\r
1095                         \r
1096                         ib_status = adapter_netpath_update_and_connect( \r
1097                                                                                                 p_adapter, p_path_record );\r
1098                         if( ib_status != IB_SUCCESS )\r
1099                         {\r
1100                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1101                                         ("IOC[%d] adapter_netpath_update_and_connect return %s\n",      \r
1102                                         p_adapter->ioc_num,\r
1103                                         p_adapter->ifc.get_err_str( ib_status )) );\r
1104                                 break;\r
1105                         }\r
1106 \r
1107                         InterlockedCompareExchange( (volatile LONG *)&p_adapter->state, \r
1108                                                                                         INIC_REGISTERED, INIC_UNINITIALIZED );\r
1109 #if ( LBFO_ENABLED )\r
1110 \r
1111                         if( p_adapter->failover.fo_state == _ADAPTER_NOT_BUNDLED )\r
1112                         {\r
1113                                 /* we don't look for zero id, since it meant to be primary by default */\r
1114                                 if( p_adapter->failover.bundle_id != 0 && \r
1115                                         ( p_primary_adapter = __adapter_find_on_failover_list( _ADAPTER_PRIMARY,\r
1116                                           p_adapter->failover.bundle_id ) ) != NULL )\r
1117                                 {\r
1118                                                 /* found matching primary */\r
1119                                                 __adapter_set_failover_secondary(\r
1120                                                                 p_adapter, p_primary_adapter->h_handle );\r
1121                                 }\r
1122                                 else\r
1123                                 {\r
1124                                         /* bundle_id '0' , all go to primary */\r
1125                                         __adapter_set_failover_primary( p_adapter, FALSE );\r
1126                                 }\r
1127                         }\r
1128 \r
1129 #endif // LBFO_ENABLED\r
1130 \r
1131                         break;\r
1132 \r
1133                 case IB_PNP_IOC_PATH_REMOVE:\r
1134                         p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
1135 \r
1136                         VNIC_TRACE( VNIC_DBG_PNP,\r
1137                                 ("IB_PNP_IOC_PATH_REMOVE (slid:%d dlid:%d) for %s.\n",\r
1138                                 ntoh16( p_ioc_path->path.slid ),\r
1139                                 ntoh16( p_ioc_path->path.dlid ),\r
1140                                 p_adapter->ioc_info.profile.id_string));\r
1141 \r
1142                         p_path_record = __path_record_remove( p_adapter, &p_ioc_path->path );\r
1143 \r
1144                         if ( p_path_record != NULL )\r
1145                         {\r
1146                                 int fail_over = 0;\r
1147 \r
1148                                 if( p_adapter->p_currentPath->p_path_rec != &p_path_record->path_rec )\r
1149                                 {\r
1150                                         VNIC_TRACE( VNIC_DBG_INFO,\r
1151                                                 ("IOC[%d] Standby Path lost\n", p_adapter->ioc_num ));\r
1152 \r
1153                                         if( p_adapter->p_currentPath !=  &p_adapter->primaryPath )\r
1154                                         {\r
1155                                                 _adapter_netpath_free( p_adapter,  &p_adapter->primaryPath );\r
1156                                         }\r
1157                                         else\r
1158                                         {\r
1159                                                 _adapter_netpath_free( p_adapter, &p_adapter->secondaryPath );\r
1160                                         }\r
1161 \r
1162                                         cl_free( p_path_record );\r
1163                                         break;\r
1164                                 }\r
1165 \r
1166                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1167                                         ("IOC[%d]Current Path lost\n", p_adapter->ioc_num ));\r
1168                                 \r
1169                                 p_netpath = p_adapter->p_currentPath;\r
1170                                 netpath_stopXmit( p_netpath );\r
1171                                 viport_timerStop( p_netpath->pViport );\r
1172 \r
1173                                 if( !p_adapter->params.SecondaryPath )\r
1174                                 {\r
1175                                         vnic_path_record_t* p_record;\r
1176 \r
1177                                         netpath_linkDown( p_netpath );\r
1178                                         _adapter_netpath_free(p_adapter, p_netpath );\r
1179 \r
1180                                         p_record = __path_record_get( p_adapter );\r
1181                                         if( p_record )\r
1182                                         {\r
1183                                                 ib_status = adapter_netpath_update_and_connect( p_adapter, p_record );\r
1184                                         }\r
1185                                         \r
1186                                         cl_free( p_path_record );\r
1187                                         break;\r
1188                                 }\r
1189 \r
1190                                 if( p_netpath == &p_adapter->primaryPath )\r
1191                                 {\r
1192                                         if( netpath_is_connected( &p_adapter->secondaryPath ) )\r
1193                                         {\r
1194                                                 netpath_stopXmit( &p_adapter->secondaryPath );\r
1195                                                 p_adapter->p_currentPath = &p_adapter->secondaryPath;\r
1196                                                 fail_over = 1;\r
1197                                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1198                                                         ("IOC[%d]Switch to Secondary Path\n", p_adapter->ioc_num ));\r
1199                                         }\r
1200                                 }\r
1201                                 else\r
1202                                 {\r
1203                                         if( netpath_is_connected( &p_adapter->primaryPath ) )\r
1204                                         {\r
1205                                                 netpath_stopXmit( &p_adapter->primaryPath );\r
1206                                                 p_adapter->p_currentPath = &p_adapter->primaryPath;\r
1207                                                 fail_over = 1;\r
1208                                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1209                                                         ("IOC[%d]Switch to Primary Path\n", p_adapter->ioc_num ));\r
1210                                         }\r
1211                                 }\r
1212                                 if( fail_over )\r
1213                                 {\r
1214                                         viport_setLink( p_adapter->p_currentPath->pViport,\r
1215                                                                 INIC_FLAG_ENABLE_NIC| INIC_FLAG_SET_MTU,\r
1216                                                                 (uint16_t)p_adapter->params.MinMtu, FALSE );\r
1217                                 }\r
1218 \r
1219                                 _adapter_netpath_free(p_adapter, p_netpath );\r
1220                                 cl_free( p_path_record );\r
1221                         }\r
1222 \r
1223                         break;\r
1224 \r
1225                 default:\r
1226                         VNIC_TRACE( VNIC_DBG_PNP,\r
1227                                 (" Received unhandled PnP event %#x\n", p_pnp_rec->pnp_event ) );\r
1228                         break;\r
1229         }\r
1230 \r
1231         VNIC_EXIT( VNIC_DBG_PNP );\r
1232         return ib_status;\r
1233 }\r
1234 \r
1235 \r
1236 NDIS_STATUS\r
1237 vnic_get_adapter_interface(\r
1238         IN      NDIS_HANDLE                     h_handle,\r
1239         IN      vnic_adapter_t          *p_adapter)\r
1240 {\r
1241         NTSTATUS                        status;\r
1242         ib_al_ifc_data_t        data;\r
1243         IO_STACK_LOCATION       io_stack;\r
1244 \r
1245         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
1246 \r
1247         NdisMGetDeviceProperty( h_handle, &p_adapter->p_pdo, NULL, NULL, NULL, NULL );\r
1248 \r
1249         data.size = sizeof(ioc_ifc_data_t);\r
1250         data.type = &GUID_IOC_INTERFACE_DATA;\r
1251         data.version = IOC_INTERFACE_DATA_VERSION;\r
1252         data.p_data = &p_adapter->ifc_data;\r
1253 \r
1254         io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
1255         io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
1256         io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
1257         io_stack.Parameters.QueryInterface.Interface = (INTERFACE*)&p_adapter->ifc;\r
1258         io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
1259         io_stack.Parameters.QueryInterface.InterfaceType = &GUID_IB_AL_INTERFACE;\r
1260 \r
1261         status = cl_fwd_query_ifc( p_adapter->p_pdo, &io_stack );\r
1262 \r
1263         if( !NT_SUCCESS( status ) )\r
1264         {\r
1265                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
1266                         ("Query interface for VNIC interface returned %08x.\n", status) );\r
1267                 return status;\r
1268         }\r
1269         /*\r
1270          * Dereference the interface now so that the bus driver doesn't fail a\r
1271          * query remove IRP.  We will always get unloaded before the bus driver\r
1272          * since we're a child device.\r
1273          */\r
1274         p_adapter->ifc.wdm.InterfaceDereference(\r
1275                 p_adapter->ifc.wdm.Context );\r
1276 \r
1277         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
1278 \r
1279         return NDIS_STATUS_SUCCESS;\r
1280 }\r
1281 \r
1282 \r
1283 static void\r
1284 __adapter_cleanup(\r
1285                 IN      vnic_adapter_t          *p_adapter )\r
1286 {\r
1287         __pending_queue_cleanup( p_adapter );\r
1288 \r
1289         __path_records_cleanup( p_adapter );\r
1290 \r
1291         _adapter_netpath_free( p_adapter, &p_adapter->primaryPath );\r
1292         _adapter_netpath_free( p_adapter, &p_adapter->secondaryPath );\r
1293 \r
1294         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
1295 }\r
1296 \r
1297 void\r
1298 __vnic_pnp_dereg_cb(\r
1299         IN                      void*                   context )\r
1300 {\r
1301         vnic_adapter_t*         p_adapter;\r
1302         ib_api_status_t         ib_status;\r
1303         ib_pnp_req_t            pnp_req;\r
1304 \r
1305         NDIS_STATUS                     ndis_status = NDIS_STATUS_SUCCESS;\r
1306 \r
1307         VNIC_ENTER( VNIC_DBG_INIT );\r
1308 \r
1309         p_adapter = (vnic_adapter_t*)context;\r
1310 \r
1311         CL_ASSERT( !p_adapter->h_pnp );\r
1312 \r
1313         /* Destroy port instances if still exist. */\r
1314         __adapter_cleanup( p_adapter );\r
1315         \r
1316         if( p_adapter->pnp_state != IB_PNP_IOC_REMOVE )\r
1317         {\r
1318                 p_adapter->pnp_state = IB_PNP_IOC_ADD;\r
1319                 /* Register for IOC events */\r
1320                 pnp_req.pfn_pnp_cb = __vnic_pnp_cb;\r
1321                 pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC;\r
1322                 pnp_req.pnp_context = (const void *)p_adapter;\r
1323 \r
1324                 ib_status = p_adapter->ifc.reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
1325                 if( ib_status != IB_SUCCESS )\r
1326                 {\r
1327                         VNIC_TRACE( VNIC_DBG_ERROR,\r
1328                                                 ("pnp_reg returned %s\n",\r
1329                                                                 p_adapter->ifc.get_err_str( ib_status )) );\r
1330                         ndis_status = NDIS_STATUS_HARD_ERRORS;\r
1331                 }\r
1332         }\r
1333         else\r
1334         {\r
1335                 ndis_status = NDIS_STATUS_HARD_ERRORS;\r
1336         }\r
1337 \r
1338         if( p_adapter->reset )\r
1339         {\r
1340                 p_adapter->reset = FALSE;\r
1341                 NdisMResetComplete( \r
1342                         p_adapter->h_handle, ndis_status, TRUE );\r
1343         }\r
1344 \r
1345         VNIC_EXIT( VNIC_DBG_INIT );\r
1346 }\r
1347 \r
1348 \r
1349 ib_api_status_t\r
1350 adapter_reset(\r
1351            IN   vnic_adapter_t* const   p_adapter )\r
1352 {\r
1353 \r
1354         ib_api_status_t         status;\r
1355         ib_pnp_handle_t         h_pnp;\r
1356 \r
1357         VNIC_ENTER( VNIC_DBG_INIT );\r
1358 \r
1359         if( p_adapter->reset )\r
1360                 return IB_INVALID_STATE;\r
1361 \r
1362         p_adapter->reset = TRUE;\r
1363         p_adapter->hung = 0;\r
1364 \r
1365 #if ( LBFO_ENABLED )\r
1366         __adapter_remove_from_failover_list( p_adapter );\r
1367 \r
1368 #endif // LBFO_ENABLED\r
1369 \r
1370         if( p_adapter->h_pnp )\r
1371         {\r
1372                 h_pnp = p_adapter->h_pnp;\r
1373                 p_adapter->h_pnp  = NULL;\r
1374                 status = p_adapter->ifc.dereg_pnp( h_pnp, __vnic_pnp_dereg_cb );\r
1375                 if( status == IB_SUCCESS )\r
1376                         status = IB_NOT_DONE;\r
1377         }\r
1378         else\r
1379         {\r
1380                 status = IB_NOT_FOUND;\r
1381         }\r
1382         \r
1383         VNIC_EXIT( VNIC_DBG_INIT );\r
1384         return status;\r
1385 }\r
1386 \r
1387 static\r
1388 NDIS_STATUS\r
1389 _adapter_set_sg_size(\r
1390                  IN             NDIS_HANDLE             h_handle,\r
1391                  IN             ULONG                   mtu_size )\r
1392 {\r
1393         NDIS_STATUS             status;\r
1394         ULONG                   buf_size;\r
1395 \r
1396         VNIC_ENTER( VNIC_DBG_INIT );\r
1397 \r
1398         buf_size = mtu_size + ETH_VLAN_HLEN;\r
1399 \r
1400         status = NdisMInitializeScatterGatherDma( h_handle, TRUE, buf_size );\r
1401 \r
1402         if ( status != NDIS_STATUS_SUCCESS )\r
1403         {\r
1404                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1405                         ("Init ScatterGatherDma failed status %#x\n", status ) );\r
1406         }\r
1407 \r
1408         VNIC_EXIT( VNIC_DBG_INIT );\r
1409         return status;\r
1410 }\r
1411 \r
1412 static ib_api_status_t\r
1413 _adapter_close_ca(\r
1414                 IN              vnic_adapter_t* const   p_adapter )\r
1415 {\r
1416         ib_api_status_t         ib_status = IB_SUCCESS;\r
1417         ib_ca_handle_t          h_ca;\r
1418 \r
1419         VNIC_ENTER( VNIC_DBG_INIT );\r
1420 \r
1421         if( !p_adapter )\r
1422                 return ib_status;\r
1423 \r
1424         VNIC_TRACE(VNIC_DBG_INIT,\r
1425                 ("IOC[%d] Close CA\n", p_adapter->ioc_num ));\r
1426 \r
1427         if( p_adapter->ca.region.h_mr )\r
1428         {\r
1429                 ib_status = p_adapter->ifc.dereg_mr( p_adapter->ca.region.h_mr );\r
1430                 if( ib_status != IB_SUCCESS )\r
1431                 {\r
1432                         VNIC_TRACE( VNIC_DBG_ERROR,\r
1433                                 ("Failed to dereg MR\n"));\r
1434                 }\r
1435                 p_adapter->ca.region.h_mr = NULL;\r
1436         }\r
1437 \r
1438         if( p_adapter->ca.hPd )\r
1439         {\r
1440                 ib_status = p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL );\r
1441                 if( ib_status != IB_SUCCESS )\r
1442                 {\r
1443                         VNIC_TRACE( VNIC_DBG_ERROR,\r
1444                                 ("Failed to dealloc PD\n"));\r
1445                 }\r
1446                 p_adapter->ca.hPd = NULL;\r
1447         }\r
1448 \r
1449         if( ( h_ca = InterlockedExchangePointer( (void *)&p_adapter->h_ca, NULL ) ) != NULL )\r
1450         {\r
1451 \r
1452                 ib_status = p_adapter->ifc.close_ca( h_ca, NULL );\r
1453                 if( ib_status != IB_SUCCESS )\r
1454                 {\r
1455                         VNIC_TRACE( VNIC_DBG_ERROR,\r
1456                                 ("Failed to close CA\n"));\r
1457                 }\r
1458         }\r
1459 \r
1460         VNIC_EXIT( VNIC_DBG_INIT );\r
1461         return ib_status;\r
1462 }\r
1463 \r
1464 static \r
1465 ib_api_status_t\r
1466 _adapter_netpath_update(\r
1467         IN              vnic_adapter_t* const   p_adapter,\r
1468         IN              viport_t* const                 p_viport,\r
1469         IN              vnic_path_record_t*             p_path )\r
1470 {\r
1471 \r
1472         Netpath_t                       *p_netpath_init;\r
1473 \r
1474         VNIC_ENTER( VNIC_DBG_PNP );\r
1475 \r
1476         NdisAcquireSpinLock( &p_adapter->lock );\r
1477         /* set primary first */\r
1478         if( !netpath_is_valid( p_adapter->p_currentPath ) )\r
1479         {\r
1480                 p_netpath_init = &p_adapter->primaryPath;\r
1481                 p_adapter->p_currentPath = p_netpath_init;\r
1482         }\r
1483 \r
1484         else \r
1485         {\r
1486                 if( p_adapter->p_currentPath != &p_adapter->primaryPath )\r
1487                 {\r
1488                         p_netpath_init = &p_adapter->primaryPath;\r
1489                 }\r
1490                 else\r
1491                 {\r
1492                         p_netpath_init = &p_adapter->secondaryPath;\r
1493                 }\r
1494         }\r
1495 \r
1496         /* shouldn't really happened ?? */\r
1497         if( netpath_is_connected( p_netpath_init ) )\r
1498         {\r
1499                 VNIC_TRACE( VNIC_DBG_WARN,\r
1500                         ("No available Netpath found for update\n"));\r
1501 \r
1502                 NdisReleaseSpinLock( &p_adapter->lock );\r
1503                 return IB_NO_MATCH;\r
1504         }\r
1505 \r
1506         p_netpath_init->p_path_rec = &p_path->path_rec;\r
1507 \r
1508         /* netpath initialization */\r
1509 \r
1510         p_netpath_init->p_adapter = p_adapter;\r
1511         p_netpath_init->pViport = p_viport;\r
1512         p_netpath_init->carrier = FALSE;\r
1513 \r
1514         /* viport initialization */\r
1515         p_viport->p_netpath = p_netpath_init;\r
1516 \r
1517         p_viport->portGuid = p_netpath_init->p_path_rec->sgid.unicast.interface_id;\r
1518         p_viport->port_config.dataConfig.ibConfig.pathInfo = *p_netpath_init->p_path_rec;\r
1519         p_viport->port_config.controlConfig.ibConfig.pathInfo = *p_netpath_init->p_path_rec;\r
1520         \r
1521         /* set our instance id per IOC */\r
1522         p_viport->port_config.controlConfig.ibConfig.connData.inicInstance = (uint8_t)p_netpath_init->instance;\r
1523         p_viport->port_config.dataConfig.ibConfig.connData.inicInstance = (uint8_t)p_netpath_init->instance;\r
1524         /* save for later use */\r
1525         p_viport->port_config.controlConfig.inicInstance = (uint8_t)p_netpath_init->instance;\r
1526                 \r
1527         p_viport->iocGuid  = p_adapter->ioc_info.profile.ioc_guid;\r
1528         p_viport->port_config.controlConfig.ibConfig.sid = p_adapter->svc_entries[0].id;\r
1529         p_viport->port_config.dataConfig.ibConfig.sid = p_adapter->svc_entries[1].id;\r
1530 \r
1531                 VNIC_TRACE( VNIC_DBG_INFO,\r
1532                 ("IOC[%d] instance %d [%s] is using SLID=%d DLID=%d Target:%s\n",\r
1533                 p_viport->ioc_num,\r
1534                 p_netpath_init->instance,\r
1535                 netpath_to_string( p_netpath_init ),\r
1536                 cl_ntoh16( p_path->path_rec.slid ),\r
1537                 cl_ntoh16( p_path->path_rec.dlid),\r
1538                 p_adapter->ioc_info.profile.id_string) );\r
1539         \r
1540         NdisReleaseSpinLock( &p_adapter->lock );\r
1541 \r
1542         VNIC_EXIT( VNIC_DBG_PNP );\r
1543         return IB_SUCCESS;\r
1544 }\r
1545 \r
1546 static\r
1547 ib_api_status_t\r
1548 adapter_netpath_update_and_connect(\r
1549         IN              vnic_adapter_t* const   p_adapter,\r
1550         IN              vnic_path_record_t*             p_path )\r
1551 {\r
1552         ib_api_status_t         ib_status;\r
1553         viport_t*                       p_viport;\r
1554 \r
1555         ib_status = adapter_viport_allocate( p_adapter, &p_viport );\r
1556         if( ib_status != IB_SUCCESS )\r
1557         {\r
1558                 VNIC_TRACE ( VNIC_DBG_ERROR,\r
1559                         ("IOC[%] Viport allocate Failed status %s\n",\r
1560                         p_adapter->ioc_num,     p_adapter->ifc.get_err_str( ib_status )) );\r
1561                 goto err;\r
1562         }\r
1563 \r
1564         ib_status = _adapter_open_ca( p_adapter );\r
1565         if( ib_status != IB_SUCCESS )\r
1566         {\r
1567                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1568                                 ("IOC[%d]Open CA failed %s\n", p_adapter->ioc_num,\r
1569                                 p_adapter->ifc.get_err_str( ib_status )) );\r
1570                 goto err;\r
1571         }\r
1572 \r
1573         ib_status = _adapter_netpath_update( p_adapter, p_viport, p_path );\r
1574         if( ib_status != IB_SUCCESS )\r
1575         {\r
1576                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1577                                 ("IOC[%d]Update New Path failed %s\n", p_adapter->ioc_num,\r
1578                                 p_adapter->ifc.get_err_str( ib_status )) );\r
1579                 goto err;\r
1580         }\r
1581 \r
1582         ib_status = viport_control_connect( p_viport );\r
1583         if( ib_status != IB_SUCCESS )\r
1584         {\r
1585                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1586                                 ("IOC[%d]Control QP connect return %s\n", p_adapter->ioc_num,\r
1587                                 p_adapter->ifc.get_err_str( ib_status )) );\r
1588                 goto err;\r
1589         }\r
1590 \r
1591         /* should call this only once */\r
1592         if( p_adapter->state == INIC_UNINITIALIZED )\r
1593         {\r
1594                 if( _adapter_set_sg_size( p_adapter->h_handle, \r
1595                         p_adapter->params.MinMtu ) != NDIS_STATUS_SUCCESS )\r
1596                 {\r
1597                         VNIC_TRACE( VNIC_DBG_ERROR,\r
1598                                 ("IOC[%d]ScatterGather Init using MTU size %d failed\n", p_adapter->ioc_num,\r
1599                                 p_adapter->params.MinMtu ) );\r
1600                         goto err;\r
1601                 }\r
1602         }\r
1603 \r
1604         ib_status = viport_data_connect( p_viport );\r
1605         if( ib_status != IB_SUCCESS )\r
1606         {\r
1607                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1608                                 ("IOC[%d]Data QP connect return %s\n", p_adapter->ioc_num,\r
1609                                 p_adapter->ifc.get_err_str( ib_status )) );\r
1610                 goto err;\r
1611         }\r
1612         \r
1613         VNIC_TRACE( VNIC_DBG_INFO,\r
1614                         ("IOC[%d] instance %d %s is CONNECTED\n",\r
1615                         p_viport->ioc_num,\r
1616                         p_viport->p_netpath->instance,\r
1617                         netpath_to_string( p_viport->p_netpath ) ));\r
1618 \r
1619         if( p_viport->state == VIPORT_CONNECTED )\r
1620         {\r
1621                 p_adapter->num_paths++;\r
1622         }\r
1623 \r
1624         if( p_adapter->num_paths > 1 &&\r
1625                 p_viport->p_netpath != p_adapter->p_currentPath )\r
1626         {\r
1627                 if ( !netpath_setUnicast( p_viport->p_netpath, \r
1628                         p_adapter->p_currentPath->pViport->hwMacAddress ) )\r
1629                 {\r
1630                         ib_status = IB_ERROR;\r
1631                         goto err;\r
1632                 }\r
1633         }\r
1634 \r
1635         return ib_status;\r
1636 \r
1637 err:\r
1638         VNIC_TRACE( VNIC_DBG_ERROR,\r
1639                 ("IOC[%d] allocate return %#x (%s)\n", p_adapter->ioc_num,\r
1640                                 ib_status, p_adapter->ifc.get_err_str( ib_status )) );\r
1641 \r
1642         if( p_viport != NULL &&  \r
1643                 p_viport->p_netpath != NULL )\r
1644         {\r
1645                 netpath_free( p_viport->p_netpath );\r
1646         }\r
1647         return ib_status;\r
1648 }\r
1649 \r
1650 #if ( LBFO_ENABLED )\r
1651 \r
1652 static void\r
1653 __adapter_add_to_failover_list(\r
1654          IN             vnic_adapter_t* const   p_adapter,\r
1655          IN             lbfo_state_t                    state )\r
1656 {\r
1657 \r
1658         CL_ASSERT( p_adapter );\r
1659         CL_ASSERT( state == _ADAPTER_PRIMARY || state == _ADAPTER_SECONDARY );\r
1660 \r
1661         p_adapter->failover.fo_state = state;\r
1662 \r
1663         if( state == _ADAPTER_PRIMARY )\r
1664         {       \r
1665                 p_adapter->failover.primary_handle = p_adapter;\r
1666                 cl_qlist_insert_tail( &g_vnic.primary_list, &p_adapter->list_item );\r
1667         }\r
1668         else\r
1669         {\r
1670                 cl_qlist_insert_tail( &g_vnic.secondary_list, &p_adapter->list_item );\r
1671         }\r
1672 }\r
1673 \r
1674 static void\r
1675 __adapter_remove_from_failover_list(\r
1676          IN             vnic_adapter_t* const   p_adapter )\r
1677 {\r
1678         lbfo_state_t lbfo_state;\r
1679         vnic_adapter_t  *p_adapter_to_promote;\r
1680         uint32_t                bundle_id;\r
1681 \r
1682         CL_ASSERT( p_adapter );\r
1683 \r
1684         lbfo_state = p_adapter->failover.fo_state;\r
1685         p_adapter->failover.fo_state = _ADAPTER_NOT_BUNDLED;\r
1686         bundle_id = p_adapter->failover.bundle_id;\r
1687 \r
1688         if( lbfo_state == _ADAPTER_PRIMARY )\r
1689         {\r
1690                 cl_qlist_remove_item( &g_vnic.primary_list, &p_adapter->list_item );\r
1691         \r
1692                 /* search for secondary adapter with same id && (id != 0 ) */\r
1693                 if( bundle_id != 0 )\r
1694                 {\r
1695                         p_adapter_to_promote =\r
1696                                 __adapter_find_on_failover_list( _ADAPTER_SECONDARY, bundle_id );\r
1697                 \r
1698                         if( p_adapter_to_promote &&\r
1699                                 p_adapter_to_promote->pnp_state != IB_PNP_IOC_REMOVE &&\r
1700                                 p_adapter_to_promote->state == INIC_REGISTERED &&\r
1701                                 p_adapter_to_promote->reset == FALSE )\r
1702                         {\r
1703                                 /* a small recursion */\r
1704                                 __adapter_set_failover_primary( p_adapter_to_promote, TRUE );\r
1705                         }\r
1706                 }\r
1707         }\r
1708         else if( lbfo_state == _ADAPTER_SECONDARY )\r
1709         {\r
1710                 cl_qlist_remove_item( &g_vnic.secondary_list, &p_adapter->list_item );\r
1711                 VNIC_TRACE( VNIC_DBG_INFO,\r
1712                                 ("IOC[%d]  LBFO bundle %d Secondary Adapter Removed\n", \r
1713                                 p_adapter->ioc_num, p_adapter->failover.bundle_id ));\r
1714         }\r
1715         else if( lbfo_state == _ADAPTER_NOT_BUNDLED )\r
1716         {\r
1717                 VNIC_TRACE( VNIC_DBG_INFO,\r
1718                 ("IOC[%d] Adapter not bundled\n", p_adapter->ioc_num ));\r
1719         }\r
1720 \r
1721         return;\r
1722 }\r
1723 \r
1724 \r
1725 static vnic_adapter_t*\r
1726 __adapter_find_on_failover_list(\r
1727         IN              lbfo_state_t    list_flag,\r
1728         IN              uint32_t                bundle_id )\r
1729 {\r
1730         vnic_adapter_t          *p_adapter = NULL;\r
1731         cl_list_item_t          *p_item;\r
1732         cl_qlist_t                      *p_qlist = ( list_flag == _ADAPTER_PRIMARY ) ?\r
1733                 &g_vnic.primary_list : &g_vnic.secondary_list;\r
1734         \r
1735         p_item = cl_qlist_head( p_qlist );\r
1736 \r
1737         while( p_item != cl_qlist_end( p_qlist ) )\r
1738         {\r
1739                 p_adapter = PARENT_STRUCT( p_item, vnic_adapter_t, list_item );\r
1740 \r
1741                 if( p_adapter &&\r
1742                         p_adapter->failover.bundle_id == bundle_id )\r
1743                 {\r
1744                         return p_adapter;\r
1745                 }\r
1746 \r
1747                 p_item = cl_qlist_next( p_item );\r
1748         }\r
1749         return NULL;\r
1750 }\r
1751 \r
1752 static NDIS_STATUS\r
1753 __adapter_set_failover_primary(\r
1754          IN             vnic_adapter_t*  const p_adapter,\r
1755          IN             BOOLEAN                 promote_secondary )\r
1756 {\r
1757         NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
1758         \r
1759         CL_ASSERT( p_adapter );\r
1760         \r
1761         if( promote_secondary )\r
1762         {\r
1763                 if( p_adapter->failover.fo_state != _ADAPTER_SECONDARY )\r
1764                 {\r
1765                         VNIC_TRACE( VNIC_DBG_ERROR,\r
1766                                 ("LBFO Can't promote NON_SECONDARY\n"));\r
1767                         return NDIS_STATUS_NOT_ACCEPTED;\r
1768                 }\r
1769                 __adapter_remove_from_failover_list( p_adapter );\r
1770                 status = NdisMPromoteMiniport( p_adapter->h_handle );\r
1771         }\r
1772 \r
1773         if( status == NDIS_STATUS_SUCCESS )\r
1774         {\r
1775                 p_adapter->failover.p_adapter = p_adapter;\r
1776                 p_adapter->failover.fo_state = _ADAPTER_PRIMARY;\r
1777                 p_adapter->failover.primary_handle = p_adapter->h_handle;\r
1778                 __adapter_add_to_failover_list( p_adapter, _ADAPTER_PRIMARY );\r
1779 \r
1780                 VNIC_TRACE( VNIC_DBG_INFO,\r
1781                         ("IOC[%d] Set LBFO bundle %d Primary Adapter\n", \r
1782                         p_adapter->ioc_num, p_adapter->failover.bundle_id ));\r
1783         }\r
1784         else\r
1785                 VNIC_TRACE( VNIC_DBG_ERROR,\r
1786                                 ("LBFO Set to Primary Failed\n"));\r
1787 \r
1788         return status;\r
1789 }\r
1790 \r
1791 static NDIS_STATUS\r
1792 __adapter_set_failover_secondary(\r
1793          IN             vnic_adapter_t* const   p_adapter,\r
1794          IN             NDIS_HANDLE                             primary_handle )\r
1795 {\r
1796         NDIS_STATUS     status;\r
1797 \r
1798         CL_ASSERT( p_adapter );\r
1799 \r
1800         status = NdisMSetMiniportSecondary( p_adapter->h_handle, primary_handle );\r
1801         \r
1802         if ( status == NDIS_STATUS_SUCCESS )\r
1803         {\r
1804                 p_adapter->failover.fo_state = _ADAPTER_SECONDARY;\r
1805                 p_adapter->failover.primary_handle = primary_handle;\r
1806                 __adapter_add_to_failover_list( p_adapter, _ADAPTER_SECONDARY );\r
1807 \r
1808                 VNIC_TRACE( VNIC_DBG_INFO,\r
1809                                 ("IOC[%d] Set LBFO bundle %d Secondary Adapter\n", \r
1810                                 p_adapter->ioc_num, p_adapter->failover.bundle_id ));\r
1811         }\r
1812 \r
1813         return status;\r
1814 }\r
1815 \r
1816 #endif //LBFO_ENABLED\r