[IPOIB_NDIS6_CM] g_stat: added to the adapter structure two previously global counter...
[mirror/winof/.git] / ulp / ipoib_NDIS6_CM / kernel / ipoib_adapter.cpp
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
4  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
5  *\r
6  * This software is available to you under the OpenIB.org BSD license\r
7  * below:\r
8  *\r
9  *     Redistribution and use in source and binary forms, with or\r
10  *     without modification, are permitted provided that the following\r
11  *     conditions are met:\r
12  *\r
13  *      - Redistributions of source code must retain the above\r
14  *        copyright notice, this list of conditions and the following\r
15  *        disclaimer.\r
16  *\r
17  *      - Redistributions in binary form must reproduce the above\r
18  *        copyright notice, this list of conditions and the following\r
19  *        disclaimer in the documentation and/or other materials\r
20  *        provided with the distribution.\r
21  *\r
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
29  * SOFTWARE.\r
30  *\r
31  * $Id: ipoib_adapter.c 4506 2009-06-23 14:40:54Z xalex $\r
32  */\r
33 \r
34 #include <precompile.h>\r
35 \r
36 \r
37 #if defined(EVENT_TRACING)\r
38 #ifdef offsetof\r
39 #undef offsetof\r
40 #endif\r
41 #include "ipoib_adapter.tmh"\r
42 #endif\r
43 \r
44 \r
45 #define ITEM_POOL_START         16\r
46 #define ITEM_POOL_GROW          16\r
47 \r
48 \r
49 /* IB Link speeds in 100bps */\r
50 #define ONE_X_IN_100BPS         25000000\r
51 #define FOUR_X_IN_100BPS        100000000\r
52 #define TWELVE_X_IN_100BPS      300000000\r
53 \r
54 \r
55 /* Declarations */\r
56 static void\r
57 adapter_construct(\r
58         IN                              ipoib_adapter_t* const          p_adapter );\r
59 \r
60 \r
61 static ib_api_status_t\r
62 adapter_init(\r
63         IN                              ipoib_adapter_t* const          p_adapter );\r
64 \r
65 \r
66 static void\r
67 __adapter_destroying(\r
68         IN                              cl_obj_t* const                         p_obj );\r
69 \r
70 \r
71 static void\r
72 __adapter_free(\r
73         IN                              cl_obj_t* const                         p_obj );\r
74 \r
75 \r
76 static ib_api_status_t\r
77 __ipoib_pnp_reg(\r
78         IN                              ipoib_adapter_t* const          p_adapter,\r
79         IN                              ib_pnp_class_t                          flags );\r
80 \r
81 \r
82 static void\r
83 __ipoib_pnp_dereg(\r
84         IN                              void*                                           context );\r
85 \r
86 \r
87 static void\r
88 __ipoib_adapter_reset(\r
89         IN                              void*   context);\r
90 \r
91 \r
92 static ib_api_status_t\r
93 __ipoib_pnp_cb(\r
94         IN                              ib_pnp_rec_t                            *p_pnp_rec );\r
95 \r
96 \r
97 /* Leaves all mcast groups when port goes down. */\r
98 static void\r
99 ipoib_clear_mcast(\r
100         IN                              ipoib_port_t* const                     p_port );\r
101 \r
102 NDIS_STATUS\r
103 ipoib_get_adapter_guids(\r
104         IN                              NDIS_HANDLE* const                      h_adapter,\r
105         IN      OUT                     ipoib_adapter_t                         *p_adapter );\r
106 \r
107 NDIS_STATUS\r
108 ipoib_get_adapter_params(\r
109         IN      OUT                     ipoib_adapter_t                         *p_adapter,\r
110         OUT                             PUCHAR                                          *p_mac,\r
111         OUT                             UINT                                            *p_len);\r
112 \r
113 \r
114 /* Implementation */\r
115 ib_api_status_t\r
116 ipoib_create_adapter(\r
117         IN                              void* const                                     h_adapter,\r
118                 OUT                     ipoib_adapter_t** const         pp_adapter )\r
119 {\r
120         ipoib_adapter_t         *p_adapter;\r
121         NDIS_STATUS                     status;\r
122         ib_api_status_t         ib_status;\r
123         cl_status_t                     cl_status;\r
124         PUCHAR                          mac;\r
125         UINT                            len;\r
126 \r
127         IPOIB_ENTER( IPOIB_DBG_INIT );\r
128 \r
129         p_adapter = (ipoib_adapter_t *) cl_zalloc( sizeof(ipoib_adapter_t) );\r
130         if( !p_adapter )\r
131         {\r
132                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
133                         ("Failed to allocate ipoib_adapter_t (%d bytes)",\r
134                         sizeof(ipoib_adapter_t)) );\r
135                 return IB_INSUFFICIENT_MEMORY;\r
136         }\r
137 \r
138         adapter_construct( p_adapter );\r
139 \r
140         p_adapter->h_adapter = h_adapter;\r
141 \r
142         p_adapter->p_ifc = (ib_al_ifc_t *) cl_zalloc( sizeof(ib_al_ifc_t) );\r
143         if( !p_adapter->p_ifc )\r
144         {\r
145                 __adapter_free( &p_adapter->obj );\r
146                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
147                         ("ipoib_create_adapter failed to alloc ipoib_ifc_t %d bytes\n",\r
148                         sizeof(ib_al_ifc_t)) );\r
149                 return IB_INSUFFICIENT_MEMORY;\r
150         }\r
151 \r
152         /* Get the CA and port GUID from the bus driver. */\r
153         status = ipoib_get_adapter_guids( (NDIS_HANDLE *const) h_adapter,  p_adapter );\r
154         if( status != NDIS_STATUS_SUCCESS )\r
155         {\r
156                 //ASSERT(FALSE);\r
157                 __adapter_free( &p_adapter->obj );\r
158                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
159                         ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );\r
160                 return IB_ERROR;\r
161         }\r
162 \r
163         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
164                         ("Port %016I64x (CA %016I64x port %d) initializing\n",\r
165                         p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
166                         p_adapter->guids.port_num) );\r
167 \r
168         cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC,\r
169                 __adapter_destroying, NULL, __adapter_free );\r
170         if( cl_status != CL_SUCCESS )\r
171         {\r
172                 __adapter_free( &p_adapter->obj );\r
173                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
174                         ("cl_obj_init returned %#x\n", cl_status) );\r
175                 return IB_ERROR;\r
176         }\r
177 \r
178         /* Read configuration parameters. */\r
179         status = ipoib_get_adapter_params( p_adapter , &mac, &len );\r
180         if( status != NDIS_STATUS_SUCCESS )\r
181         {\r
182                 cl_obj_destroy( &p_adapter->obj );\r
183                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
184                         ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );\r
185                 return IB_ERROR;\r
186         }\r
187                 \r
188         ib_status = adapter_init( p_adapter );\r
189         if( ib_status != IB_SUCCESS )\r
190         {\r
191                 cl_obj_destroy( &p_adapter->obj );\r
192                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
193                         ("adapter_init returned %s.\n", \r
194                         p_adapter->p_ifc->get_err_str( ib_status )) );\r
195                 return ib_status;\r
196         }\r
197 \r
198         ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, p_adapter->mac.addr );\r
199         /* If there is a NetworkAddress override in registry, use it */\r
200         if( (len == HW_ADDR_LEN) && (mac != NULL) )\r
201         {\r
202                 if( ETH_IS_MULTICAST(mac) || ETH_IS_BROADCAST(mac) ||\r
203                         !ETH_IS_LOCALLY_ADMINISTERED(mac) )\r
204                 {\r
205                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
206                                 ("Overriding NetworkAddress is invalid - "\r
207                                 "%02x-%02x-%02x-%02x-%02x-%02x\n",\r
208                                 mac[0], mac[1], mac[2],\r
209                                 mac[3], mac[4], mac[5]) );\r
210                 }\r
211                 else\r
212         {\r
213                         ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, mac );\r
214                 }\r
215         }\r
216 \r
217         p_adapter->p_stat = ipoib_st_dev_add();\r
218         if ( p_adapter->p_stat ) \r
219                 p_adapter->p_stat->p_adapter = p_adapter;\r
220 \r
221         *pp_adapter = p_adapter;\r
222 \r
223         IPOIB_EXIT( IPOIB_DBG_INIT );\r
224         return IB_SUCCESS;\r
225 }\r
226 \r
227 \r
228 ib_api_status_t\r
229 ipoib_start_adapter(\r
230         IN                              ipoib_adapter_t* const          p_adapter )\r
231 {\r
232         ib_api_status_t status;\r
233 \r
234         IPOIB_ENTER( IPOIB_DBG_INIT );\r
235 \r
236         status = __ipoib_pnp_reg( p_adapter,\r
237                 IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE );\r
238 \r
239         IPOIB_EXIT( IPOIB_DBG_INIT );\r
240         return status;\r
241 }\r
242 \r
243 \r
244 void\r
245 ipoib_destroy_adapter(\r
246         IN                              ipoib_adapter_t* const          p_adapter )\r
247 {\r
248         PIPOIB_ST_DEVICE p_stat;\r
249 \r
250         IPOIB_ENTER( IPOIB_DBG_INIT );\r
251 \r
252         CL_ASSERT( p_adapter );\r
253 \r
254         // statistics\r
255         p_stat = p_adapter->p_stat;\r
256         if ( p_stat ) {\r
257                 p_stat->p_halt_thread = KeGetCurrentThread();\r
258                 p_stat->p_prev_port = p_adapter->p_port;\r
259         }\r
260 \r
261         /*\r
262          * Flag the adapter as being removed.  We use the IB_PNP_PORT_REMOVE state\r
263          * for this purpose.  Note that we protect this state change with both the\r
264          * mutex and the lock.  The mutex provides synchronization as a whole\r
265          * between destruction and AL callbacks (PnP, Query, Destruction).\r
266          * The lock provides protection\r
267          */\r
268         KeWaitForMutexObject(\r
269                 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
270         cl_obj_lock( &p_adapter->obj );\r
271         p_adapter->state = IB_PNP_PORT_REMOVE;\r
272 \r
273         /*\r
274          * Clear the pointer to the port object since the object destruction\r
275          * will cascade to child objects.  This prevents potential duplicate\r
276          * destruction (or worse, stale pointer usage).\r
277          */\r
278         p_adapter->p_port = NULL;\r
279 \r
280         cl_obj_unlock( &p_adapter->obj );\r
281 \r
282         KeReleaseMutex( &p_adapter->mutex, FALSE );\r
283 \r
284         cl_obj_destroy( &p_adapter->obj );\r
285         ipoib_st_dev_rmv( p_stat );\r
286 \r
287         IPOIB_EXIT( IPOIB_DBG_INIT );\r
288 }\r
289 \r
290 \r
291 static void\r
292 adapter_construct(\r
293         IN                              ipoib_adapter_t* const          p_adapter )\r
294 {\r
295         cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );\r
296         cl_spinlock_construct( &p_adapter->send_stat_lock );\r
297         cl_spinlock_construct( &p_adapter->recv_stat_lock );\r
298         cl_qpool_construct( &p_adapter->item_pool );\r
299         KeInitializeMutex( &p_adapter->mutex, 0 );\r
300 \r
301         cl_thread_construct(&p_adapter->destroy_thread);\r
302         \r
303         cl_vector_construct( &p_adapter->ip_vector );\r
304 \r
305         cl_perf_construct( &p_adapter->perf );\r
306 \r
307         p_adapter->state = IB_PNP_PORT_ADD;\r
308         p_adapter->port_rate = FOUR_X_IN_100BPS;\r
309 }\r
310 \r
311 \r
312 static ib_api_status_t\r
313 adapter_init(\r
314         IN                              ipoib_adapter_t* const          p_adapter )\r
315 {\r
316         cl_status_t                     cl_status;\r
317         ib_api_status_t         status;\r
318 \r
319         IPOIB_ENTER( IPOIB_DBG_INIT );\r
320 \r
321         cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );\r
322         if( cl_status != CL_SUCCESS )\r
323         {\r
324                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
325                         ("cl_perf_init returned %#x\n", cl_status) );\r
326                 return IB_ERROR;\r
327         }\r
328 \r
329         cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );\r
330         if( cl_status != CL_SUCCESS )\r
331         {\r
332                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
333                         ("cl_spinlock_init returned %#x\n", cl_status) );\r
334                 return IB_ERROR;\r
335         }\r
336 \r
337         cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );\r
338         if( cl_status != CL_SUCCESS )\r
339         {\r
340                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
341                         ("cl_spinlock_init returned %#x\n", cl_status) );\r
342                 return IB_ERROR;\r
343         }\r
344 \r
345         cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,\r
346                 ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );\r
347         if( cl_status != CL_SUCCESS )\r
348         {\r
349                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
350                         ("cl_qpool_init returned %#x\n", cl_status) );\r
351                 return IB_ERROR;\r
352         }\r
353 \r
354 \r
355         /* We manually manage the size and capacity of the vector. */\r
356         cl_status = cl_vector_init( &p_adapter->ip_vector, 0,\r
357                 0, sizeof(net_address_item_t), NULL, NULL, p_adapter );\r
358         if( cl_status != CL_SUCCESS )\r
359         {\r
360                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
361                         ("cl_vector_init for ip_vector returned %#x\n",\r
362                         cl_status) );\r
363                 return IB_ERROR;\r
364         }\r
365 \r
366         /* Validate the port GUID and generate the MAC address. */\r
367         status =\r
368                 ipoib_mac_from_guid( p_adapter->guids.port_guid.guid, p_adapter->params.guid_mask, &p_adapter->mac);\r
369         if( status != IB_SUCCESS )\r
370         {\r
371                 if( status == IB_INVALID_GUID_MASK )\r
372                 {\r
373                         IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
374                                 ("Invalid GUID mask received, rejecting it") );\r
375                         ipoib_create_log(p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
376                 }\r
377 \r
378                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
379                         ("ipoib_mac_from_guid returned %s\n", \r
380                         p_adapter->p_ifc->get_err_str( status )) );\r
381                 return status;\r
382         }\r
383 \r
384         /* Open AL. */\r
385         status = p_adapter->p_ifc->open_al( &p_adapter->h_al );\r
386         if( status != IB_SUCCESS )\r
387         {\r
388                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
389                         ("ib_open_al returned %s\n", \r
390                         p_adapter->p_ifc->get_err_str( status )) );\r
391                 return status;\r
392         }\r
393 \r
394         IPOIB_EXIT( IPOIB_DBG_INIT );\r
395         return status;\r
396 }\r
397 \r
398 \r
399 static ib_api_status_t\r
400 __ipoib_pnp_reg(\r
401         IN                              ipoib_adapter_t* const          p_adapter,\r
402         IN                              ib_pnp_class_t                          flags )\r
403 {\r
404         ib_api_status_t         status;\r
405         ib_pnp_req_t            pnp_req;\r
406         \r
407         IPOIB_ENTER( IPOIB_DBG_INIT );\r
408 \r
409         CL_ASSERT( !p_adapter->h_pnp );\r
410         CL_ASSERT( !p_adapter->registering );\r
411 \r
412         p_adapter->registering = TRUE;\r
413         \r
414         /* Register for PNP events. */\r
415         cl_memclr( &pnp_req, sizeof(pnp_req) );\r
416         pnp_req.pnp_class = IB_PNP_PORT | flags;\r
417         /*\r
418          * Context is the cl_obj of the adapter to allow passing cl_obj_deref\r
419          * to ib_dereg_pnp.\r
420          */\r
421         pnp_req.pnp_context = &p_adapter->obj;\r
422         pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;\r
423         status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
424         if( status != IB_SUCCESS )\r
425         {\r
426                 //ASSERT(FALSE);\r
427                 p_adapter->registering = FALSE;\r
428                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
429                         ("ib_reg_pnp returned %s\n", \r
430                         p_adapter->p_ifc->get_err_str( status )) );\r
431                 return status;\r
432         }\r
433         /*\r
434          * Reference the adapter on behalf of the PNP registration.\r
435          * This allows the destruction to block until the PNP deregistration\r
436          * completes.\r
437          */\r
438         cl_obj_ref( &p_adapter->obj );\r
439         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
440                                 ("[%p] Adapter refcount raised to %d\n", p_adapter, p_adapter->obj.ref_cnt));\r
441 \r
442 \r
443         IPOIB_EXIT( IPOIB_DBG_INIT );\r
444         return status;\r
445 }\r
446 \r
447 \r
448 static void\r
449 __adapter_destroying(\r
450         IN                              cl_obj_t* const                         p_obj )\r
451 {\r
452         ipoib_adapter_t         *p_adapter;\r
453         KLOCK_QUEUE_HANDLE      hdl;\r
454 \r
455         IPOIB_ENTER( IPOIB_DBG_INIT );\r
456 \r
457         p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
458 \r
459         /*\r
460          * The adapter's object will be dereferenced when the deregistration\r
461          * completes.  No need to lock here since all PnP related API calls\r
462          * are driven by NDIS (via the Init/Reset/Destroy paths).\r
463          */\r
464         if( p_adapter->h_pnp )\r
465         {\r
466                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
467                                 ("Adapter[%p] has refcnt= %d\n", p_adapter, p_adapter->obj.ref_cnt));\r
468                 p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, (ib_pfn_destroy_cb_t) cl_obj_deref );\r
469                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
470                                 ("Adapter[%p] refcnt decremented to %d\n", p_adapter, p_adapter->obj.ref_cnt));\r
471                 p_adapter->h_pnp = NULL;\r
472         }\r
473 \r
474         if( p_adapter->packet_filter )\r
475         {\r
476                 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
477                 cl_obj_lock( &p_adapter->obj );\r
478 \r
479                 ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
480                 cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry );\r
481 \r
482                 p_adapter->packet_filter = 0;\r
483 \r
484                 cl_obj_unlock( &p_adapter->obj );\r
485                 KeReleaseInStackQueuedSpinLock( &hdl );\r
486         }\r
487 \r
488         IPOIB_EXIT( IPOIB_DBG_INIT );\r
489 }\r
490 \r
491 \r
492 static void\r
493 __adapter_free(\r
494         IN                              cl_obj_t* const                         p_obj )\r
495 {\r
496         ipoib_adapter_t *p_adapter;\r
497 \r
498         IPOIB_ENTER( IPOIB_DBG_INIT );\r
499 \r
500         p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
501 \r
502         if( p_adapter->p_ifc )\r
503         {\r
504                 if( p_adapter->h_al )\r
505                         p_adapter->p_ifc->close_al( p_adapter->h_al );\r
506 \r
507                 cl_free( p_adapter->p_ifc );\r
508                 p_adapter->p_ifc = NULL;\r
509         }\r
510 \r
511         cl_vector_destroy( &p_adapter->ip_vector );\r
512         cl_qpool_destroy( &p_adapter->item_pool );\r
513         cl_spinlock_destroy( &p_adapter->recv_stat_lock );\r
514         cl_spinlock_destroy( &p_adapter->send_stat_lock );\r
515         cl_obj_deinit( p_obj );\r
516 \r
517         cl_perf_destroy( &p_adapter->perf, TRUE );\r
518 \r
519         cl_free( p_adapter );\r
520 \r
521         IPOIB_EXIT( IPOIB_DBG_INIT );\r
522 }\r
523 \r
524 \r
525 static ib_api_status_t\r
526 ipoib_query_pkey_index(ipoib_adapter_t  *p_adapter)\r
527 {\r
528         ib_api_status_t                 status;\r
529         ib_ca_attr_t                *ca_attr;\r
530         uint32_t                            ca_size;\r
531         uint16_t index = 0;\r
532 \r
533         /* Query the CA for Pkey table */\r
534         status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, NULL, &ca_size);\r
535         if(status != IB_INSUFFICIENT_MEMORY)\r
536         {\r
537                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
538                                                 ("ib_query_ca failed\n"));\r
539                 return status;\r
540         }\r
541 \r
542         ca_attr = (ib_ca_attr_t*)cl_zalloc(ca_size);\r
543         if      (!ca_attr)\r
544         {\r
545                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
546                                                 ("cl_zalloc can't allocate %d\n",ca_size));\r
547                 return IB_INSUFFICIENT_MEMORY;\r
548         }\r
549 \r
550         status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, ca_attr,&ca_size);  \r
551         if( status != IB_SUCCESS )\r
552         {\r
553                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
554                                                 ("ib_query_ca returned %s\n", \r
555                                                  p_adapter->p_ifc->get_err_str( status )) );\r
556                 goto pkey_end;\r
557         }\r
558         CL_ASSERT(ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[0] == IB_DEFAULT_PKEY);\r
559         for(index = 0; index < ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys; index++)\r
560         {\r
561                 if(cl_hton16(p_adapter->guids.port_guid.pkey) == ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[index])\r
562                         break;\r
563         }\r
564         if(index >= ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys)\r
565         {\r
566                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
567                                                 ("Pkey table is invalid, index not found\n"));\r
568                 NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
569                         EVENT_IPOIB_PARTITION_ERR, 1, p_adapter->guids.port_guid.pkey );\r
570                 status = IB_NOT_FOUND;\r
571                 p_adapter->p_port->pkey_index = PKEY_INVALID_INDEX;\r
572                 goto pkey_end;\r
573         }\r
574 \r
575         p_adapter->p_port->pkey_index = index;\r
576         IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_IB,\r
577                                         ("for PKEY = 0x%04X got index = %d\n",p_adapter->guids.port_guid.pkey,index));\r
578 \r
579 pkey_end:\r
580         if(ca_attr)\r
581                 cl_free(ca_attr);\r
582         return status;\r
583 }\r
584 \r
585 static inline void __ipoib_get_down(\r
586         IN ipoib_adapter_t              *p_adapter) \r
587 {\r
588 \r
589         NDIS_LINK_STATE         link_state;\r
590         NDIS_STATUS_INDICATION  status_indication;\r
591         \r
592         link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
593         link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
594         link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
595         link_state.MediaConnectState = MediaConnectStateDisconnected;\r
596         link_state.MediaDuplexState = MediaDuplexStateFull;\r
597         link_state.XmitLinkSpeed = \r
598         link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
599         link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
600 \r
601         IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
602                            p_adapter->h_adapter,\r
603                            NDIS_STATUS_LINK_STATE,\r
604                            (PVOID)&link_state,\r
605                            sizeof(link_state));\r
606 \r
607         NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
608         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
609                 ("Link DOWN!\n") );\r
610 \r
611         ipoib_port_down( p_adapter->p_port );\r
612 }\r
613 \r
614 static ib_api_status_t\r
615 __ipoib_pnp_cb(\r
616         IN                              ib_pnp_rec_t                            *p_pnp_rec )\r
617 {\r
618         ipoib_adapter_t         *p_adapter;\r
619         ipoib_port_t            *p_port;\r
620         ib_pnp_event_t          old_state;\r
621         ib_pnp_port_rec_t       *p_port_rec;\r
622         ib_api_status_t         status = IB_SUCCESS;\r
623         NDIS_LINK_STATE         link_state;\r
624         NDIS_STATUS_INDICATION  status_indication;\r
625 \r
626         IPOIB_ENTER( IPOIB_DBG_PNP );\r
627 \r
628         CL_ASSERT( p_pnp_rec );\r
629         NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
630         p_adapter =\r
631                 PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );\r
632 \r
633         CL_ASSERT( p_adapter );\r
634 \r
635         /* Synchronize with destruction */\r
636         KeWaitForMutexObject(\r
637                 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
638         cl_obj_lock( &p_adapter->obj );\r
639         old_state = p_adapter->state;\r
640         cl_obj_unlock( &p_adapter->obj );\r
641         if( old_state == IB_PNP_PORT_REMOVE )\r
642         {\r
643                 KeReleaseMutex( &p_adapter->mutex, FALSE );\r
644                 IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
645                         ("Aborting - Adapter destroying.\n") );\r
646                 return IB_NOT_DONE;\r
647         }\r
648 \r
649         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
650                 ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
651                 p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
652 \r
653         p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec;\r
654 \r
655         switch( p_pnp_rec->pnp_event )\r
656         {\r
657         case IB_PNP_PORT_ADD:\r
658                 CL_ASSERT( !p_pnp_rec->context );\r
659                 /* Only process our port GUID. */\r
660                 if( p_pnp_rec->guid != p_adapter->guids.port_guid.guid )\r
661                 {\r
662                         status = IB_NOT_DONE;\r
663                         break;\r
664                 }\r
665 \r
666                 /* Don't process if we're destroying. */\r
667                 if( p_adapter->obj.state == CL_DESTROYING )\r
668                 {\r
669                         status = IB_NOT_DONE;\r
670                         break;\r
671                 }\r
672 \r
673                 CL_ASSERT( !p_adapter->p_port );\r
674                 /* Allocate all IB resources. */\r
675                 cl_obj_lock( &p_adapter->obj );\r
676                 p_adapter->state = IB_PNP_PORT_ADD;\r
677                 cl_obj_unlock( &p_adapter->obj );\r
678                 status = ipoib_create_port( p_adapter, p_port_rec, &p_port );\r
679                 cl_obj_lock( &p_adapter->obj );\r
680                 if( status != IB_SUCCESS )\r
681                 {\r
682                         p_adapter->state = old_state;\r
683                         cl_obj_unlock( &p_adapter->obj );\r
684                         p_adapter->hung = TRUE;\r
685                         break;\r
686                 }\r
687 \r
688                 p_pnp_rec->context = p_port;\r
689                 if ( p_adapter->p_stat ) \r
690                         p_adapter->p_stat->p_prev_port = p_adapter->p_port;\r
691                 p_adapter->p_port = p_port;\r
692                 cl_obj_unlock( &p_adapter->obj );\r
693                 break;\r
694 \r
695         case IB_PNP_PORT_REMOVE:\r
696 \r
697                 if (p_adapter->state != IB_PNP_PORT_DOWN) {\r
698                         IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ALL, \r
699                                 (" Port got IB_PNP_PORT_REMOVE before IB_PNP_PORT_DOWN\n"));\r
700                         __ipoib_get_down( p_adapter);\r
701                 }\r
702 \r
703                 /* Release all IB resources. */\r
704                 CL_ASSERT( p_pnp_rec->context );\r
705 \r
706                 cl_obj_lock( &p_adapter->obj );\r
707                 p_adapter->state = IB_PNP_PORT_REMOVE;\r
708                 p_port = p_adapter->p_port;\r
709                 p_adapter->p_port = NULL;\r
710                 if ( p_adapter->p_stat ) \r
711                         p_adapter->p_stat->p_prev_port = p_port;\r
712                 cl_obj_unlock( &p_adapter->obj );\r
713                 ipoib_port_destroy( p_port );\r
714                 p_pnp_rec->context = NULL;\r
715                 status = IB_SUCCESS;\r
716                 break;\r
717 \r
718         case IB_PNP_PORT_ACTIVE:\r
719                 /* Join multicast groups and put QP in RTS. */\r
720                 CL_ASSERT( p_pnp_rec->context );\r
721 \r
722                 cl_obj_lock( &p_adapter->obj );\r
723                 p_adapter->state = IB_PNP_PORT_INIT;\r
724                 cl_obj_unlock( &p_adapter->obj );\r
725                 ipoib_port_up( p_adapter->p_port, p_port_rec );\r
726 \r
727                 status = IB_SUCCESS;\r
728                 break;\r
729 \r
730         case IB_PNP_PORT_ARMED:\r
731                 status = IB_SUCCESS;\r
732                 break;\r
733 \r
734         case IB_PNP_PORT_INIT:\r
735                 /*\r
736                  * Init could happen if the SM brings the port down\r
737                  * without changing the physical link.\r
738                  */\r
739         case IB_PNP_PORT_DOWN:\r
740                 CL_ASSERT( p_pnp_rec->context );\r
741 \r
742                 cl_obj_lock( &p_adapter->obj );\r
743                 old_state = p_adapter->state;\r
744                 p_adapter->state = IB_PNP_PORT_DOWN;\r
745                 cl_obj_unlock( &p_adapter->obj );\r
746                 status = IB_SUCCESS;\r
747 \r
748                 if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN )\r
749                 {\r
750                         __ipoib_get_down( p_adapter );\r
751                 }\r
752                 break;\r
753 \r
754         case IB_PNP_REG_COMPLETE:\r
755                 if( p_adapter->registering )\r
756                 {\r
757                         p_adapter->registering = FALSE;\r
758                         cl_obj_lock( &p_adapter->obj );\r
759                         old_state = p_adapter->state;\r
760                         cl_obj_unlock( &p_adapter->obj );\r
761 \r
762                         if( old_state == IB_PNP_PORT_DOWN )\r
763                         {\r
764                                 /* If we were initializing, we might have pended some OIDs. */\r
765                                 ipoib_resume_oids( p_adapter );\r
766 \r
767                                 link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
768                                 link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
769                                 link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
770                                 link_state.MediaConnectState = MediaConnectStateDisconnected;\r
771                                 link_state.MediaDuplexState = MediaDuplexStateFull;\r
772                                 link_state.XmitLinkSpeed = \r
773                                 link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
774                                 link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
775 \r
776                                 IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
777                                                                            p_adapter->h_adapter,\r
778                                                                            NDIS_STATUS_LINK_STATE,\r
779                                                                            (PVOID)&link_state,\r
780                                                                            sizeof(link_state));\r
781                                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, ("Indicate DISCONNECT\n") );\r
782                                 NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);                 \r
783                         }\r
784                 }\r
785 \r
786                 if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT )\r
787                 {\r
788                         p_adapter->reset = FALSE;\r
789                         NdisMResetComplete(\r
790                                 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
791                 }\r
792                 status = IB_SUCCESS;\r
793                 break;\r
794 \r
795         default:\r
796                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
797                         ("IPOIB: Received unhandled PnP event 0x%x (%s)\n",\r
798                         p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
799                 /* Fall through. */\r
800 \r
801                 status = IB_SUCCESS;\r
802 \r
803                 /* We ignore events below if the link is not active. */\r
804                 if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE )\r
805                         break;\r
806 \r
807                 case IB_PNP_PKEY_CHANGE:\r
808                         if(p_pnp_rec->pnp_event == IB_PNP_PKEY_CHANGE && \r
809                            p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
810                         {\r
811                                 status = ipoib_query_pkey_index(p_adapter);\r
812                                 if(status != IB_SUCCESS)\r
813                                 {\r
814                                    cl_obj_lock( &p_adapter->obj );\r
815                                    p_adapter->state = IB_PNP_PORT_INIT;\r
816                                    cl_obj_unlock( &p_adapter->obj );\r
817                                 }\r
818                         }\r
819 \r
820                 case IB_PNP_SM_CHANGE:\r
821                 case IB_PNP_GID_CHANGE:\r
822                 case IB_PNP_LID_CHANGE:\r
823 \r
824                 cl_obj_lock( &p_adapter->obj );\r
825                 old_state = p_adapter->state;\r
826                 switch( old_state )\r
827                 {\r
828                 case IB_PNP_PORT_DOWN:\r
829                         p_adapter->state = IB_PNP_PORT_INIT;\r
830                         break;\r
831 \r
832                 default:\r
833                         p_adapter->state = IB_PNP_PORT_DOWN;\r
834                 }\r
835                 cl_obj_unlock( &p_adapter->obj );\r
836                 \r
837                 if( p_adapter->registering )\r
838                         break;\r
839 \r
840                 switch( old_state )\r
841                 {\r
842                 case IB_PNP_PORT_ACTIVE:\r
843                 case IB_PNP_PORT_INIT:\r
844                         link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
845                         link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
846                         link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
847                         link_state.MediaConnectState = MediaConnectStateDisconnected;\r
848                         link_state.MediaDuplexState = MediaDuplexStateFull;\r
849                         link_state.XmitLinkSpeed = \r
850                         link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
851                         link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
852 \r
853                         IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
854                                                                    p_adapter->h_adapter,\r
855                                                                    NDIS_STATUS_LINK_STATE,\r
856                                                                    (PVOID)&link_state,\r
857                                                                    sizeof(link_state));\r
858 \r
859                         NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);         \r
860 \r
861                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
862                                 ("Link DOWN!\n") );\r
863                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
864                         ("Indicate DISCONNECT\n") );\r
865 \r
866                         ipoib_port_down( p_adapter->p_port );\r
867                         /* Fall through. */\r
868 \r
869                 case IB_PNP_PORT_DOWN:\r
870                         cl_obj_lock( &p_adapter->obj );\r
871                         p_adapter->state = IB_PNP_PORT_INIT;\r
872                         cl_obj_unlock( &p_adapter->obj );\r
873                         ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );\r
874                 }\r
875                 break;\r
876         }\r
877 \r
878         KeReleaseMutex( &p_adapter->mutex, FALSE );\r
879 \r
880         IPOIB_EXIT( IPOIB_DBG_PNP );\r
881         return status;\r
882 }\r
883 \r
884 \r
885 /* Joins/leaves mcast groups based on currently programmed mcast MACs. */\r
886 void\r
887 ipoib_refresh_mcast(\r
888         IN                              ipoib_adapter_t* const          p_adapter,\r
889         IN                              mac_addr_t* const                       p_mac_array,\r
890         IN              const   uint8_t                                         num_macs )\r
891 {\r
892         uint8_t                         i, j;\r
893         ipoib_port_t            *p_port = NULL;\r
894 \r
895         IPOIB_ENTER( IPOIB_DBG_MCAST );\r
896         cl_obj_lock( &p_adapter->obj );\r
897         if( p_adapter->state == IB_PNP_PORT_ACTIVE )\r
898         {\r
899                 p_port = p_adapter->p_port;\r
900                 ipoib_port_ref( p_port, ref_refresh_mcast );\r
901         }\r
902         cl_obj_unlock( &p_adapter->obj );\r
903 \r
904         if( p_port )\r
905         {\r
906                 /* Purge old entries. */\r
907                 for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
908                 {\r
909                         for( j = 0; j < num_macs; j++ )\r
910                         {\r
911                                 if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],\r
912                                         sizeof(mac_addr_t) ) )\r
913                                 {\r
914                                         break;\r
915                                 }\r
916                         }\r
917                         if( j != num_macs )\r
918                                 continue;\r
919 \r
920                         ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );\r
921                 }\r
922 \r
923                 /* Add new entries */\r
924                 for( i = 0; i < num_macs; i++ )\r
925                 {\r
926                         for( j = 0; j < p_adapter->mcast_array_size; j++ )\r
927                         {\r
928                                 if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],\r
929                                         sizeof(mac_addr_t) ) )\r
930                                 {\r
931                                         break;\r
932                                 }\r
933                         }\r
934 \r
935                         if( j != p_adapter->mcast_array_size )\r
936                                 continue;\r
937                         if ( ( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e &&\r
938                                    p_mac_array[i].addr[3] == 0 && p_mac_array[i].addr[4] == 0 && p_mac_array[i].addr[5] == 1 ) ||\r
939                                   !( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e )\r
940                                 )\r
941                         {\r
942                                 \r
943                                 ipoib_port_join_mcast( p_port, p_mac_array[i], IB_MC_REC_STATE_FULL_MEMBER );\r
944                         }\r
945                 }\r
946         }\r
947 \r
948         /* Copy the MAC array. */\r
949         NdisMoveMemory( p_adapter->mcast_array, p_mac_array,\r
950                 num_macs * sizeof(mac_addr_t) );\r
951         p_adapter->mcast_array_size = num_macs;\r
952 \r
953         if( p_port )\r
954                 ipoib_port_deref( p_port, ref_refresh_mcast );\r
955 \r
956         IPOIB_EXIT( IPOIB_DBG_MCAST );\r
957 }\r
958 \r
959 \r
960 ib_api_status_t\r
961 ipoib_reset_adapter(\r
962         IN                              ipoib_adapter_t* const          p_adapter )\r
963 {\r
964         ib_api_status_t         status;\r
965         ib_pnp_handle_t         h_pnp;\r
966 \r
967         IPOIB_ENTER( IPOIB_DBG_INIT );\r
968 \r
969         if( p_adapter->reset )\r
970                 return IB_INVALID_STATE;\r
971 \r
972         p_adapter->hung = FALSE;\r
973         p_adapter->reset = TRUE;\r
974 \r
975         if( p_adapter->h_pnp )\r
976         {\r
977                 h_pnp = p_adapter->h_pnp;\r
978                 p_adapter->h_pnp  = NULL;\r
979                 status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg );\r
980                 if( status == IB_SUCCESS )\r
981                         status = IB_NOT_DONE;\r
982         }\r
983         else\r
984         {\r
985                 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
986                 if( status == IB_SUCCESS )\r
987                         p_adapter->hung = FALSE;\r
988         }\r
989         if (status == IB_NOT_DONE) {\r
990                 p_adapter->reset = TRUE;\r
991         }\r
992         else {\r
993                 p_adapter->reset = FALSE;\r
994         }\r
995         IPOIB_EXIT( IPOIB_DBG_INIT );\r
996         return status;\r
997 }\r
998 \r
999 \r
1000 static void\r
1001 __ipoib_pnp_dereg(\r
1002         IN                              void*                                           context )\r
1003 {\r
1004         ipoib_adapter_t*        p_adapter;\r
1005 \r
1006         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1007 \r
1008         p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );\r
1009 \r
1010         cl_thread_init(&p_adapter->destroy_thread, __ipoib_adapter_reset, (void*)p_adapter, "destroy_thread");\r
1011         \r
1012         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1013 \r
1014 }\r
1015 \r
1016 static void\r
1017 __ipoib_adapter_reset(\r
1018         IN                              void*   context)\r
1019 {\r
1020 \r
1021         ipoib_adapter_t *p_adapter;\r
1022         ipoib_port_t            *p_port;\r
1023         ib_api_status_t         status;\r
1024         ib_pnp_event_t          state;\r
1025         \r
1026         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1027         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1028                                 ("Got RESET\n") );\r
1029 \r
1030         p_adapter = (ipoib_adapter_t*)context;\r
1031         \r
1032         /* Synchronize with destruction */\r
1033         KeWaitForMutexObject(\r
1034                 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
1035 \r
1036         cl_obj_lock( &p_adapter->obj );\r
1037 \r
1038         CL_ASSERT( !p_adapter->h_pnp );\r
1039 \r
1040         if( p_adapter->state != IB_PNP_PORT_REMOVE )\r
1041                 p_adapter->state = IB_PNP_PORT_ADD;\r
1042 \r
1043         state = p_adapter->state;\r
1044 \r
1045         /* Destroy the current port instance if it still exists. */\r
1046         p_port = p_adapter->p_port;\r
1047         p_adapter->p_port = NULL;\r
1048         if ( p_adapter->p_stat ) \r
1049                 p_adapter->p_stat->p_prev_port = p_port;\r
1050         cl_obj_unlock( &p_adapter->obj );\r
1051 \r
1052         if( p_port )\r
1053                 ipoib_port_destroy( p_port );\r
1054         ASSERT(p_adapter->reset == TRUE);\r
1055         if( state != IB_PNP_PORT_REMOVE )\r
1056         {\r
1057                 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
1058                 if( status != IB_SUCCESS )\r
1059                 {\r
1060                         p_adapter->reset = FALSE;\r
1061                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1062                                 ("__ipoib_pnp_reg returned %s\n",\r
1063                                 p_adapter->p_ifc->get_err_str( status )) );\r
1064                         NdisMResetComplete( \r
1065                                 p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );\r
1066                 }\r
1067         }\r
1068         else\r
1069         {\r
1070                 p_adapter->reset = FALSE;\r
1071                 NdisMResetComplete(\r
1072                         p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
1073                 status = IB_SUCCESS;\r
1074         }\r
1075 \r
1076         /* Dereference the adapter since the previous registration is now gone. */\r
1077         cl_obj_deref( &p_adapter->obj );\r
1078         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
1079                         ("Adapter[%p] refcnt decremented to %d\n", p_adapter, p_adapter->obj.ref_cnt));\r
1080 \r
1081         KeReleaseMutex( &p_adapter->mutex, FALSE );\r
1082 \r
1083         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1084 }\r
1085 \r
1086 \r
1087 void\r
1088 ipoib_set_rate(\r
1089         IN                              ipoib_adapter_t* const          p_adapter,\r
1090         IN              const   uint8_t                                         link_width, \r
1091         IN              const   uint8_t                                         link_speed )\r
1092 {\r
1093         uint32_t        rate;\r
1094 \r
1095         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1096 \r
1097         /* Set the link speed based on the IB link speed (1x vs 4x, etc). */\r
1098         switch( link_speed )\r
1099         {\r
1100         case IB_LINK_SPEED_ACTIVE_2_5:\r
1101                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
1102                         ("Link speed is 2.5Gs\n") );\r
1103                 rate = IB_LINK_SPEED_ACTIVE_2_5;\r
1104                 break;\r
1105 \r
1106         case IB_LINK_SPEED_ACTIVE_5:\r
1107                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
1108                         ("Link speed is 5G\n") );\r
1109                 rate = IB_LINK_SPEED_ACTIVE_5;\r
1110                 break;\r
1111 \r
1112         case IB_LINK_SPEED_ACTIVE_10:\r
1113                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
1114                         ("Link speed is 10G\n") );\r
1115                 rate = IB_LINK_SPEED_ACTIVE_10;\r
1116                 break;\r
1117 \r
1118         default:\r
1119                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1120                         ("Invalid link speed %d.\n", link_speed) );\r
1121                 rate = 0;\r
1122         }\r
1123 \r
1124         switch( link_width )\r
1125         {\r
1126         case IB_LINK_WIDTH_ACTIVE_1X:\r
1127                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
1128                         ("Link width is 1X\n") );\r
1129                 rate *= ONE_X_IN_100BPS;\r
1130                 break;\r
1131 \r
1132         case IB_LINK_WIDTH_ACTIVE_4X:\r
1133                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
1134                         ("Link width is 4X\n") );\r
1135                 rate *= FOUR_X_IN_100BPS;\r
1136                 break;\r
1137 \r
1138         case IB_LINK_WIDTH_ACTIVE_12X:\r
1139                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
1140                         ("Link width is 12X\n") );\r
1141                 rate *= TWELVE_X_IN_100BPS;\r
1142                 break;\r
1143 \r
1144         default:\r
1145                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1146                         ("Invalid link rate (%d).\n", link_width) );\r
1147                 rate = 0;\r
1148         }\r
1149 \r
1150         p_adapter->port_rate = rate;\r
1151         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1152 }\r
1153 \r
1154 \r
1155 ib_api_status_t\r
1156 ipoib_set_active(\r
1157         IN                              ipoib_adapter_t* const          p_adapter )\r
1158 {\r
1159         ib_pnp_event_t  old_state;\r
1160         uint8_t                 i;\r
1161         ib_api_status_t status = IB_SUCCESS;\r
1162         NDIS_LINK_STATE         link_state;\r
1163         NDIS_STATUS_INDICATION  status_indication;\r
1164         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1165 \r
1166         NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
1167         cl_obj_lock( &p_adapter->obj );\r
1168         old_state = p_adapter->state;\r
1169 \r
1170         /* Change the state to indicate that we are now connected and live. */\r
1171         if( old_state == IB_PNP_PORT_INIT )\r
1172                 p_adapter->state = IB_PNP_PORT_ACTIVE;\r
1173 \r
1174         cl_obj_unlock( &p_adapter->obj );\r
1175 \r
1176         /*\r
1177          * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
1178          * complete it now.\r
1179          */\r
1180         switch( old_state )\r
1181         {\r
1182         case IB_PNP_PORT_ADD:\r
1183                 ipoib_reg_addrs( p_adapter );\r
1184                 /* Fall through. */\r
1185 \r
1186         case IB_PNP_PORT_REMOVE:\r
1187                 ipoib_resume_oids( p_adapter );\r
1188                 break;\r
1189 \r
1190         default:\r
1191                 if (p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
1192                 {\r
1193                         status = ipoib_query_pkey_index(p_adapter);\r
1194                         if( IB_SUCCESS != status)\r
1195                         {\r
1196                                 break;\r
1197                         }\r
1198                 }\r
1199                 /* Join all programmed multicast groups. */\r
1200                 for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
1201                 {\r
1202                         IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,("Calling join mcast from ipoib_set_active\n"));\r
1203                         ipoib_port_join_mcast(\r
1204                                 p_adapter->p_port, p_adapter->mcast_array[i] ,IB_MC_REC_STATE_FULL_MEMBER);\r
1205                 }\r
1206 \r
1207                 /* Register all existing addresses. */\r
1208                 ipoib_reg_addrs( p_adapter );\r
1209 \r
1210                 ipoib_resume_oids( p_adapter );\r
1211 \r
1212                 /*\r
1213                  * Now that we're in the broadcast group, notify that\r
1214                  * we have a link.\r
1215                  */\r
1216                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Link UP!\n") );\r
1217                 NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
1218                         EVENT_IPOIB_PORT_UP + (p_adapter->port_rate/ONE_X_IN_100BPS),\r
1219                         1, p_adapter->port_rate );\r
1220 \r
1221                 if( !p_adapter->reset )\r
1222                 {\r
1223                         link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
1224                         link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
1225                         link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
1226                         link_state.MediaConnectState = MediaConnectStateConnected;\r
1227                         link_state.MediaDuplexState = MediaDuplexStateFull;\r
1228                         link_state.XmitLinkSpeed = \r
1229                         link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
1230                         link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
1231                         IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
1232                                                                    p_adapter->h_adapter,\r
1233                                                                    NDIS_STATUS_LINK_STATE,\r
1234                                                                    (PVOID)&link_state,\r
1235                                                                    sizeof(link_state));\r
1236                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("***************Indicate connect!\n") );\r
1237                         NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
1238                 }\r
1239         }\r
1240 \r
1241         if( p_adapter->reset )\r
1242         {\r
1243                 //ASSERT(FALSE);\r
1244                 p_adapter->reset = FALSE;\r
1245                 NdisMResetComplete(\r
1246                         p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
1247         }\r
1248 \r
1249         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1250         return  status;\r
1251 }\r
1252 \r
1253 /*\r
1254  * If something goes wrong after the port goes active, e.g.\r
1255  *      - PortInfo query failure\r
1256  *      - MC Join timeout\r
1257  *      - etc\r
1258  * Mark the port state as down, resume any pended OIDS, etc.\r
1259  */\r
1260 void\r
1261 ipoib_set_inactive(\r
1262         IN                              ipoib_adapter_t* const          p_adapter )\r
1263 {\r
1264         ib_pnp_event_t  old_state;\r
1265         NDIS_LINK_STATE         link_state;\r
1266         NDIS_STATUS_INDICATION  status_indication;\r
1267 \r
1268         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1269 \r
1270         NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
1271         cl_obj_lock( &p_adapter->obj );\r
1272         old_state = p_adapter->state;\r
1273         if( old_state != IB_PNP_PORT_REMOVE )\r
1274                 p_adapter->state = IB_PNP_PORT_DOWN;\r
1275         cl_obj_unlock( &p_adapter->obj );\r
1276 \r
1277         /*\r
1278          * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
1279          * complete it now.\r
1280          */\r
1281         if( old_state == IB_PNP_PORT_INIT )\r
1282         {\r
1283                 link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
1284                 link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
1285                 link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
1286                 link_state.MediaConnectState = MediaConnectStateDisconnected;\r
1287                 link_state.MediaDuplexState = MediaDuplexStateFull;\r
1288                 link_state.XmitLinkSpeed = \r
1289                 link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
1290                 link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
1291 \r
1292                 IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
1293                                                            p_adapter->h_adapter,\r
1294                                                            NDIS_STATUS_LINK_STATE,\r
1295                                                            (PVOID)&link_state,\r
1296                                                            sizeof(link_state));\r
1297                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Disconnect!\n") );\r
1298                 NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
1299 \r
1300                 ipoib_resume_oids( p_adapter );\r
1301         }\r
1302 \r
1303         if( p_adapter->reset )\r
1304         {\r
1305                 p_adapter->reset = FALSE;\r
1306                 NdisMResetComplete(\r
1307                         p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
1308         }\r
1309 \r
1310         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1311 }\r
1312 \r
1313 NDIS_STATUS\r
1314 ipoib_get_gen_stat(\r
1315         IN                              ipoib_adapter_t* const          p_adapter,\r
1316         OUT             pending_oid_t* const            p_oid_info)\r
1317 {\r
1318         PNDIS_STATISTICS_INFO StatisticsInfo;\r
1319         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1320 \r
1321         if (p_oid_info->buf_len < sizeof(StatisticsInfo))\r
1322         {\r
1323                 *p_oid_info->p_bytes_needed = sizeof(NDIS_STATISTICS_INFO);\r
1324                 return NDIS_STATUS_INVALID_LENGTH;\r
1325         }\r
1326 \r
1327         StatisticsInfo = (PNDIS_STATISTICS_INFO)p_oid_info->p_buf;\r
1328     StatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1;\r
1329     StatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
1330     StatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO);\r
1331     /*StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS          |\r
1332                                           NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR             |\r
1333                                                                                   NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV   |\r
1334                                           NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV  |\r
1335                                                                                   NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV  |\r
1336                                           NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV             | \r
1337                                           NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV   |\r
1338                                                                                   NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV       |\r
1339                                                                                   NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV        |\r
1340 \r
1341                                                                                   NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS                     |\r
1342                                                                                   NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR            |\r
1343                                                                                   NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT  | \r
1344                                           NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
1345                                                                                   NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
1346                                                                                   NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT                        |\r
1347                                                                                   NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT       |\r
1348                                                                                   NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT      |\r
1349                                                                                   NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; */\r
1350                                                                                   \r
1351                                                                                   \r
1352         StatisticsInfo->SupportedStatistics =  NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |\r
1353                                                                                         //The data in the ifHCInUcastPkts member is valid. \r
1354                                                                                         NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |\r
1355                                                                                         //The data in the ifHCInMulticastPkts member is valid. \r
1356                                                                                         NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |\r
1357                                                                                         //The data in the ifHCInBroadcastPkts member is valid. \r
1358                                                                                         NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |\r
1359                                                                                         //The data in the ifHCInOctets member is valid. \r
1360                                                                                         NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |\r
1361                                                                                         //The data in the ifInDiscards member is valid. \r
1362                                                                                         NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |\r
1363                                                                                         //The data in the ifInErrors member is valid. \r
1364                                                                                         NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |\r
1365                                                                                         //The data in the ifHCOutUcastPkts member is valid. \r
1366                                                                                         NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
1367                                                                                         //The data in the ifHCOutMulticastPkts member is valid. \r
1368                                                                                         NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
1369                                                                                         //The data in the ifHCOutBroadcastPkts member is valid. \r
1370                                                                                         NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |\r
1371                                                                                         //The data in the ifHCOutOctets member is valid. \r
1372                                                                                         NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |\r
1373                                                                                         //The data in the ifOutErrors member is valid. \r
1374                                                                                         NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |\r
1375                                                                                         //The data in the ifOutDiscards member is valid. \r
1376                                                                                         NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |\r
1377                                                                                         //The data in the ifHCInUcastOctets member is valid. \r
1378                                                                                         NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |\r
1379                                                                                         //The data in the ifHCInMulticastOctets member is valid. \r
1380                                                                                         NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |\r
1381                                                                                         //The data in the ifHCInBroadcastOctets member is valid. \r
1382                                                                                         NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |\r
1383                                                                                         //The data in the ifHCOutUcastOctets member is valid. \r
1384                                                                                         NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |\r
1385                                                                                         //The data in the ifHCOutMulticastOctets member is valid. \r
1386                                                                                         NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT ;\r
1387                                                                                         //The data in the ifHCOutBroadcastOctets member is valid\r
1388 \r
1389     cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
1390     StatisticsInfo->ifInDiscards = p_adapter->recv_stats.comp.dropped +\r
1391                                    p_adapter->recv_stats.comp.error;            \r
1392     StatisticsInfo->ifInErrors = p_adapter->recv_stats.comp.error;\r
1393     StatisticsInfo->ifHCInOctets = p_adapter->recv_stats.ucast.bytes + \r
1394                                                                    p_adapter->recv_stats.bcast.bytes + \r
1395                                                                    p_adapter->recv_stats.mcast.bytes;       \r
1396     StatisticsInfo->ifHCInUcastPkts       = p_adapter->recv_stats.ucast.frames;\r
1397     StatisticsInfo->ifHCInMulticastPkts   = p_adapter->recv_stats.mcast.frames;  \r
1398     StatisticsInfo->ifHCInBroadcastPkts   = p_adapter->recv_stats.bcast.frames;  \r
1399         StatisticsInfo->ifHCInMulticastOctets = p_adapter->recv_stats.mcast.bytes;\r
1400         StatisticsInfo->ifHCInBroadcastOctets = p_adapter->recv_stats.bcast.bytes;\r
1401         StatisticsInfo->ifHCInUcastOctets     = p_adapter->recv_stats.ucast.bytes;\r
1402         cl_spinlock_release( &p_adapter->recv_stat_lock );\r
1403 \r
1404     cl_spinlock_acquire( &p_adapter->send_stat_lock ); \r
1405     StatisticsInfo->ifHCOutOctets = p_adapter->send_stats.ucast.bytes + \r
1406                                                                         p_adapter->send_stats.mcast.bytes + \r
1407                                                                         p_adapter->send_stats.bcast.bytes;        \r
1408     StatisticsInfo->ifHCOutUcastPkts       = p_adapter->send_stats.ucast.frames;     \r
1409     StatisticsInfo->ifHCOutMulticastPkts   = p_adapter->send_stats.mcast.frames; \r
1410     StatisticsInfo->ifHCOutBroadcastPkts   = p_adapter->send_stats.bcast.frames; \r
1411     StatisticsInfo->ifOutErrors            = p_adapter->send_stats.comp.error;                                      \r
1412     StatisticsInfo->ifOutDiscards          = p_adapter->send_stats.comp.dropped;\r
1413         StatisticsInfo->ifHCOutUcastOctets     = p_adapter->send_stats.ucast.bytes;\r
1414         StatisticsInfo->ifHCOutMulticastOctets = p_adapter->send_stats.mcast.bytes;\r
1415         StatisticsInfo->ifHCOutBroadcastOctets = p_adapter->send_stats.bcast.bytes;\r
1416     cl_spinlock_release( &p_adapter->send_stat_lock );\r
1417 \r
1418         *p_oid_info->p_bytes_used = sizeof(NDIS_STATISTICS_INFO);\r
1419 \r
1420         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1421         return NDIS_STATUS_SUCCESS;\r
1422 }\r
1423 \r
1424 NDIS_STATUS\r
1425 ipoib_get_recv_stat(\r
1426         IN                              ipoib_adapter_t* const          p_adapter,\r
1427         IN              const   ip_stat_sel_t                           stat_sel,\r
1428         IN                              pending_oid_t* const            p_oid_info )\r
1429 {\r
1430         uint64_t        stat;\r
1431 \r
1432         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1433 \r
1434         CL_ASSERT( p_adapter );\r
1435 \r
1436         cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
1437         switch( stat_sel )\r
1438         {\r
1439         case IP_STAT_SUCCESS:\r
1440                 stat = p_adapter->recv_stats.comp.success;\r
1441                 break;\r
1442 \r
1443         case IP_STAT_ERROR:\r
1444                 stat = p_adapter->recv_stats.comp.error;\r
1445                 break;\r
1446 \r
1447         case IP_STAT_DROPPED:\r
1448                 stat = p_adapter->recv_stats.comp.dropped;\r
1449                 break;\r
1450 \r
1451         case IP_STAT_UCAST_BYTES:\r
1452                 stat = p_adapter->recv_stats.ucast.bytes;\r
1453                 break;\r
1454 \r
1455         case IP_STAT_UCAST_FRAMES:\r
1456                 stat = p_adapter->recv_stats.ucast.frames;\r
1457                 break;\r
1458 \r
1459         case IP_STAT_BCAST_BYTES:\r
1460                 stat = p_adapter->recv_stats.bcast.bytes;\r
1461                 break;\r
1462 \r
1463         case IP_STAT_BCAST_FRAMES:\r
1464                 stat = p_adapter->recv_stats.bcast.frames;\r
1465                 break;\r
1466 \r
1467         case IP_STAT_MCAST_BYTES:\r
1468                 stat = p_adapter->recv_stats.mcast.bytes;\r
1469                 break;\r
1470 \r
1471         case IP_STAT_MCAST_FRAMES:\r
1472                 stat = p_adapter->recv_stats.mcast.frames;\r
1473                 break;\r
1474 \r
1475         default:\r
1476                 stat = 0;\r
1477         }\r
1478         cl_spinlock_release( &p_adapter->recv_stat_lock );\r
1479 \r
1480         *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
1481 \r
1482         if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
1483         {\r
1484                 *((uint64_t*)p_oid_info->p_buf) = stat;\r
1485                 *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
1486         }\r
1487         else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
1488         {\r
1489                 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
1490                 *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
1491         }\r
1492         else\r
1493         {\r
1494                 *p_oid_info->p_bytes_used = 0;\r
1495                 IPOIB_EXIT( IPOIB_DBG_STAT );\r
1496                 return NDIS_STATUS_INVALID_LENGTH;\r
1497         }\r
1498 \r
1499         IPOIB_EXIT( IPOIB_DBG_STAT );\r
1500         return NDIS_STATUS_SUCCESS;\r
1501 }\r
1502 \r
1503 \r
1504 void\r
1505 ipoib_inc_recv_stat(\r
1506         IN                              ipoib_adapter_t* const          p_adapter,\r
1507         IN              const   ip_stat_sel_t                           stat_sel,\r
1508         IN              const   size_t                                          bytes OPTIONAL,\r
1509         IN              const   size_t                                          packets OPTIONAL )\r
1510 {\r
1511         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1512 \r
1513         cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
1514         switch( stat_sel )\r
1515         {\r
1516         case IP_STAT_ERROR:\r
1517                 p_adapter->recv_stats.comp.error++;\r
1518                 break;\r
1519 \r
1520         case IP_STAT_DROPPED:\r
1521                 p_adapter->recv_stats.comp.dropped++;\r
1522                 break;\r
1523 \r
1524         case IP_STAT_UCAST_BYTES:\r
1525         case IP_STAT_UCAST_FRAMES:\r
1526                 p_adapter->recv_stats.comp.success++;\r
1527                 p_adapter->recv_stats.ucast.frames += packets;\r
1528                 p_adapter->recv_stats.ucast.bytes += bytes;\r
1529                 break;\r
1530 \r
1531         case IP_STAT_BCAST_BYTES:\r
1532         case IP_STAT_BCAST_FRAMES:\r
1533                 p_adapter->recv_stats.comp.success++;\r
1534                 p_adapter->recv_stats.bcast.frames += packets;\r
1535                 p_adapter->recv_stats.bcast.bytes += bytes;\r
1536                 break;\r
1537 \r
1538         case IP_STAT_MCAST_BYTES:\r
1539         case IP_STAT_MCAST_FRAMES:\r
1540                 p_adapter->recv_stats.comp.success++;\r
1541                 p_adapter->recv_stats.mcast.frames += packets;\r
1542                 p_adapter->recv_stats.mcast.bytes += bytes;\r
1543                 break;\r
1544 \r
1545         default:\r
1546                 break;\r
1547         }\r
1548         cl_spinlock_release( &p_adapter->recv_stat_lock );\r
1549 \r
1550         IPOIB_EXIT( IPOIB_DBG_STAT );\r
1551 }\r
1552 \r
1553 NDIS_STATUS\r
1554 ipoib_get_send_stat(\r
1555         IN                              ipoib_adapter_t* const          p_adapter,\r
1556         IN              const   ip_stat_sel_t                           stat_sel,\r
1557         IN                              pending_oid_t* const            p_oid_info )\r
1558 {\r
1559         uint64_t        stat;\r
1560 \r
1561         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1562 \r
1563         CL_ASSERT( p_adapter );\r
1564 \r
1565         cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
1566         switch( stat_sel )\r
1567         {\r
1568         case IP_STAT_SUCCESS:\r
1569                 stat = p_adapter->send_stats.comp.success;\r
1570                 break;\r
1571 \r
1572         case IP_STAT_ERROR:\r
1573                 stat = p_adapter->send_stats.comp.error;\r
1574                 break;\r
1575 \r
1576         case IP_STAT_DROPPED:\r
1577                 stat = p_adapter->send_stats.comp.dropped;\r
1578                 break;\r
1579 \r
1580         case IP_STAT_UCAST_BYTES:\r
1581                 stat = p_adapter->send_stats.ucast.bytes;\r
1582                 break;\r
1583 \r
1584         case IP_STAT_UCAST_FRAMES:\r
1585                 stat = p_adapter->send_stats.ucast.frames;\r
1586                 break;\r
1587 \r
1588         case IP_STAT_BCAST_BYTES:\r
1589                 stat = p_adapter->send_stats.bcast.bytes;\r
1590                 break;\r
1591 \r
1592         case IP_STAT_BCAST_FRAMES:\r
1593                 stat = p_adapter->send_stats.bcast.frames;\r
1594                 break;\r
1595 \r
1596         case IP_STAT_MCAST_BYTES:\r
1597                 stat = p_adapter->send_stats.mcast.bytes;\r
1598                 break;\r
1599 \r
1600         case IP_STAT_MCAST_FRAMES:\r
1601                 stat = p_adapter->send_stats.mcast.frames;\r
1602                 break;\r
1603 \r
1604         default:\r
1605                 stat = 0;\r
1606         }\r
1607         cl_spinlock_release( &p_adapter->send_stat_lock );\r
1608 \r
1609         *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
1610 \r
1611         if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
1612         {\r
1613                 *((uint64_t*)p_oid_info->p_buf) = stat;\r
1614                 *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
1615         }\r
1616         else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
1617         {\r
1618                 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
1619                 *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
1620         }\r
1621         else\r
1622         {\r
1623                 *p_oid_info->p_bytes_used = 0;\r
1624                 IPOIB_EXIT( IPOIB_DBG_STAT );\r
1625                 return NDIS_STATUS_INVALID_LENGTH;\r
1626         }\r
1627 \r
1628         IPOIB_EXIT( IPOIB_DBG_STAT );\r
1629         return NDIS_STATUS_SUCCESS;\r
1630 }\r
1631 \r
1632 \r
1633 void\r
1634 ipoib_inc_send_stat(\r
1635         IN                              ipoib_adapter_t* const          p_adapter,\r
1636         IN              const   ip_stat_sel_t                           stat_sel,\r
1637         IN              const   size_t                                          bytes OPTIONAL )\r
1638 {\r
1639         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1640 \r
1641         cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
1642         switch( stat_sel )\r
1643         {\r
1644         case IP_STAT_ERROR:\r
1645                 p_adapter->send_stats.comp.error++;\r
1646                 break;\r
1647 \r
1648         case IP_STAT_DROPPED:\r
1649                 p_adapter->send_stats.comp.dropped++;\r
1650                 break;\r
1651 \r
1652         case IP_STAT_UCAST_BYTES:\r
1653         case IP_STAT_UCAST_FRAMES:\r
1654                 p_adapter->send_stats.comp.success++;\r
1655                 p_adapter->send_stats.ucast.frames++;\r
1656                 p_adapter->send_stats.ucast.bytes += bytes;\r
1657                 break;\r
1658 \r
1659         case IP_STAT_BCAST_BYTES:\r
1660         case IP_STAT_BCAST_FRAMES:\r
1661                 p_adapter->send_stats.comp.success++;\r
1662                 p_adapter->send_stats.bcast.frames++;\r
1663                 p_adapter->send_stats.bcast.bytes += bytes;\r
1664                 break;\r
1665 \r
1666         case IP_STAT_MCAST_BYTES:\r
1667         case IP_STAT_MCAST_FRAMES:\r
1668                 p_adapter->send_stats.comp.success++;\r
1669                 p_adapter->send_stats.mcast.frames++;\r
1670                 p_adapter->send_stats.mcast.bytes += bytes;\r
1671                 break;\r
1672 \r
1673         default:\r
1674                 break;\r
1675         }\r
1676         cl_spinlock_release( &p_adapter->send_stat_lock );\r
1677 \r
1678         IPOIB_EXIT( IPOIB_DBG_STAT );\r
1679 }\r