[IPoIB] Use PnP string conversion in debug output.
[mirror/winof/.git] / ulp / ipoib / kernel / ipoib_adapter.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 \r
34 #include "ipoib_adapter.h"\r
35 #include "ipoib_port.h"\r
36 #include "ipoib_driver.h"\r
37 #include "ipoib_debug.h"\r
38 \r
39 #if defined(EVENT_TRACING)\r
40 #ifdef offsetof\r
41 #undef offsetof\r
42 #endif\r
43 #include "ipoib_adapter.tmh"\r
44 #endif\r
45 \r
46 \r
47 #define ITEM_POOL_START         16\r
48 #define ITEM_POOL_GROW          16\r
49 \r
50 \r
51 /* IB Link speeds in 100bps */\r
52 #define ONE_X_IN_100BPS         25000000\r
53 #define FOUR_X_IN_100BPS        100000000\r
54 #define TWELVE_X_IN_100BPS      300000000\r
55 \r
56 \r
57 /* Declarations */\r
58 static void\r
59 adapter_construct(\r
60         IN                              ipoib_adapter_t* const          p_adapter );\r
61 \r
62 \r
63 static ib_api_status_t\r
64 adapter_init(\r
65         IN                              ipoib_adapter_t* const          p_adapter );\r
66 \r
67 \r
68 static void\r
69 __adapter_destroying(\r
70         IN                              cl_obj_t* const                         p_obj );\r
71 \r
72 \r
73 static void\r
74 __adapter_cleanup(\r
75         IN                              cl_obj_t* const                         p_obj );\r
76 \r
77 \r
78 static void\r
79 __adapter_free(\r
80         IN                              cl_obj_t* const                         p_obj );\r
81 \r
82 \r
83 static ib_api_status_t\r
84 __ipoib_pnp_reg(\r
85         IN                              ipoib_adapter_t* const          p_adapter,\r
86         IN                              ib_pnp_class_t                          flags );\r
87 \r
88 \r
89 static void\r
90 __ipoib_pnp_dereg(\r
91         IN                              void*                                           context );\r
92 \r
93 \r
94 static ib_api_status_t\r
95 __ipoib_pnp_cb(\r
96         IN                              ib_pnp_rec_t                            *p_pnp_rec );\r
97 \r
98 \r
99 static void\r
100 ipoib_destroy_port(\r
101         IN                              ipoib_adapter_t* const          p_adapter );\r
102 \r
103 \r
104 void\r
105 ipoib_join_mcast(\r
106         IN                              ipoib_adapter_t* const          p_adapter );\r
107 \r
108 \r
109 /* Leaves all mcast groups when port goes down. */\r
110 static void\r
111 ipoib_clear_mcast(\r
112         IN                              ipoib_port_t* const                     p_port );\r
113 \r
114 NDIS_STATUS\r
115 ipoib_get_adapter_guids(\r
116         IN                              NDIS_HANDLE* const                      h_adapter,\r
117         IN      OUT                     ipoib_adapter_t                         *p_adapter );\r
118 \r
119 NDIS_STATUS\r
120 ipoib_get_adapter_params(\r
121         IN                              NDIS_HANDLE* const                      wrapper_config_context,\r
122         IN      OUT                     ipoib_adapter_t                         *p_adapter );\r
123 \r
124 \r
125 /* Implementation */\r
126 ib_api_status_t\r
127 ipoib_create_adapter(\r
128         IN                              NDIS_HANDLE                                     wrapper_config_context,\r
129         IN                              void* const                                     h_adapter,\r
130                 OUT                     ipoib_adapter_t** const         pp_adapter )\r
131 {\r
132         ipoib_adapter_t         *p_adapter;\r
133         ib_api_status_t         status;\r
134         cl_status_t                     cl_status;\r
135 \r
136         IPOIB_ENTER( IPOIB_DBG_INIT );\r
137 \r
138         p_adapter = cl_zalloc( sizeof(ipoib_adapter_t) );\r
139         if( !p_adapter )\r
140         {\r
141                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
142                         ("Failed to allocate ipoib_adapter_t (%d bytes)",\r
143                         sizeof(ipoib_adapter_t)) );\r
144                 return IB_INSUFFICIENT_MEMORY;\r
145         }\r
146 \r
147         adapter_construct( p_adapter );\r
148 \r
149         p_adapter->h_adapter = h_adapter;\r
150 \r
151         p_adapter->p_ifc = cl_zalloc( sizeof(ib_al_ifc_t) );\r
152         if( !p_adapter->p_ifc )\r
153         {\r
154                 __adapter_free( &p_adapter->obj );\r
155                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
156                         ("ipoib_create_adapter failed to alloc ipoib_ifc_t %d bytes\n",\r
157                         sizeof(ib_al_ifc_t)) );\r
158                 return IB_INSUFFICIENT_MEMORY;\r
159         }\r
160 \r
161         /* Get the CA and port GUID from the bus driver. */\r
162         status = ipoib_get_adapter_guids( h_adapter,  p_adapter );\r
163         if( status != NDIS_STATUS_SUCCESS )\r
164         {\r
165                 __adapter_free( &p_adapter->obj );\r
166                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
167                         ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );\r
168                 return status;\r
169         }\r
170 \r
171         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
172                         ("Port %016I64x (CA %016I64x port %d) initializing\n",\r
173                         p_adapter->guids.port_guid, p_adapter->guids.ca_guid,\r
174                         p_adapter->guids.port_num) );\r
175 \r
176         cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC,\r
177                 __adapter_destroying, NULL, __adapter_free );\r
178         if( cl_status != CL_SUCCESS )\r
179         {\r
180                 __adapter_free( &p_adapter->obj );\r
181                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
182                         ("cl_obj_init returned %s\n", cl_status_text[cl_status]) );\r
183                 return IB_ERROR;\r
184         }\r
185 \r
186         status = adapter_init( p_adapter );\r
187         if( status != IB_SUCCESS )\r
188         {\r
189                 cl_obj_destroy( &p_adapter->obj );\r
190                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
191                         ("adapter_init returned %s.\n", \r
192                         p_adapter->p_ifc->get_err_str( status )) );\r
193                 return status;\r
194         }\r
195 \r
196         /* Read configuration parameters. */\r
197         status = ipoib_get_adapter_params( wrapper_config_context,\r
198                 p_adapter );\r
199         if( status != NDIS_STATUS_SUCCESS )\r
200         {\r
201                 cl_obj_destroy( &p_adapter->obj );\r
202                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
203                         ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );\r
204                 return status;\r
205         }\r
206 \r
207         *pp_adapter = p_adapter;\r
208 \r
209         IPOIB_EXIT( IPOIB_DBG_INIT );\r
210         return status;\r
211 }\r
212 \r
213 \r
214 ib_api_status_t\r
215 ipoib_start_adapter(\r
216         IN                              ipoib_adapter_t* const          p_adapter )\r
217 {\r
218         ib_api_status_t status;\r
219 \r
220         IPOIB_ENTER( IPOIB_DBG_INIT );\r
221 \r
222         status = __ipoib_pnp_reg( p_adapter,\r
223                 IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE );\r
224 \r
225         IPOIB_EXIT( IPOIB_DBG_INIT );\r
226         return status;\r
227 }\r
228 \r
229 \r
230 void\r
231 ipoib_destroy_adapter(\r
232         IN                              ipoib_adapter_t* const          p_adapter )\r
233 {\r
234         IPOIB_ENTER( IPOIB_DBG_INIT );\r
235 \r
236         CL_ASSERT( p_adapter );\r
237 \r
238         /*\r
239          * Flag the adapter as being removed.  We use the IB_PNP_PORT_REMOVE state\r
240          * for this purpose.  Note that we protect this state change with both the\r
241          * mutex and the lock.  The mutex provides synchronization as a whole\r
242          * between destruction and AL callbacks (PnP, Query, Destruction).\r
243          * The lock provides protection\r
244          */\r
245         KeWaitForMutexObject(\r
246                 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
247         cl_obj_lock( &p_adapter->obj );\r
248         p_adapter->state = IB_PNP_PORT_REMOVE;\r
249 \r
250         /*\r
251          * Clear the pointer to the port object since the object destruction\r
252          * will cascade to child objects.  This prevents potential duplicate\r
253          * destruction (or worse, stale pointer usage).\r
254          */\r
255         p_adapter->p_port = NULL;\r
256 \r
257         cl_obj_unlock( &p_adapter->obj );\r
258 \r
259         KeReleaseMutex( &p_adapter->mutex, FALSE );\r
260 \r
261         cl_obj_destroy( &p_adapter->obj );\r
262 \r
263         IPOIB_EXIT( IPOIB_DBG_INIT );\r
264 }\r
265 \r
266 \r
267 static void\r
268 adapter_construct(\r
269         IN                              ipoib_adapter_t* const          p_adapter )\r
270 {\r
271         cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );\r
272         cl_spinlock_construct( &p_adapter->send_stat_lock );\r
273         cl_spinlock_construct( &p_adapter->recv_stat_lock );\r
274         cl_qpool_construct( &p_adapter->item_pool );\r
275         KeInitializeMutex( &p_adapter->mutex, 0 );\r
276         cl_vector_construct( &p_adapter->ip_vector );\r
277 \r
278         cl_perf_construct( &p_adapter->perf );\r
279 \r
280         p_adapter->state = IB_PNP_PORT_ADD;\r
281         p_adapter->rate = FOUR_X_IN_100BPS;\r
282 }\r
283 \r
284 \r
285 static ib_api_status_t\r
286 adapter_init(\r
287         IN                              ipoib_adapter_t* const          p_adapter )\r
288 {\r
289         cl_status_t                     cl_status;\r
290         ib_api_status_t         status;\r
291 \r
292         IPOIB_ENTER( IPOIB_DBG_INIT );\r
293 \r
294         cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );\r
295         if( cl_status != CL_SUCCESS )\r
296         {\r
297                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
298                         ("cl_perf_init returned %s\n", cl_status_text[cl_status]) );\r
299                 return IB_ERROR;\r
300         }\r
301 \r
302         cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );\r
303         if( cl_status != CL_SUCCESS )\r
304         {\r
305                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
306                         ("cl_spinlock_init returned %s\n", cl_status_text[cl_status]) );\r
307                 return IB_ERROR;\r
308         }\r
309 \r
310         cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );\r
311         if( cl_status != CL_SUCCESS )\r
312         {\r
313                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
314                         ("cl_spinlock_init returned %s\n", cl_status_text[cl_status]) );\r
315                 return IB_ERROR;\r
316         }\r
317 \r
318         cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,\r
319                 ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );\r
320         if( cl_status != CL_SUCCESS )\r
321         {\r
322                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
323                         ("cl_qpool_init returned %s\n", cl_status_text[cl_status]) );\r
324                 return IB_ERROR;\r
325         }\r
326 \r
327 \r
328         /* We manually manage the size and capacity of the vector. */\r
329         cl_status = cl_vector_init( &p_adapter->ip_vector, 0,\r
330                 0, sizeof(net_address_item_t), NULL, NULL, p_adapter );\r
331         if( cl_status != CL_SUCCESS )\r
332         {\r
333                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
334                         ("cl_vector_init for ip_vector returned %s\n",\r
335                         CL_STATUS_MSG(cl_status)) );\r
336                 return IB_ERROR;\r
337         }\r
338 \r
339         /* Validate the port GUID and generate the MAC address. */\r
340         status =\r
341                 ipoib_mac_from_guid( p_adapter->guids.port_guid, &p_adapter->mac );\r
342         if( status != IB_SUCCESS )\r
343         {\r
344                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
345                         ("ipoib_mac_from_guid returned %s\n", \r
346                         p_adapter->p_ifc->get_err_str( status )) );\r
347                 return status;\r
348         }\r
349 \r
350         /* Open AL. */\r
351         status = p_adapter->p_ifc->open_al( &p_adapter->h_al );\r
352         if( status != IB_SUCCESS )\r
353         {\r
354                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
355                         ("ib_open_al returned %s\n", \r
356                         p_adapter->p_ifc->get_err_str( status )) );\r
357                 return status;\r
358         }\r
359 \r
360         IPOIB_EXIT( IPOIB_DBG_INIT );\r
361         return status;\r
362 }\r
363 \r
364 \r
365 static ib_api_status_t\r
366 __ipoib_pnp_reg(\r
367         IN                              ipoib_adapter_t* const          p_adapter,\r
368         IN                              ib_pnp_class_t                          flags )\r
369 {\r
370         ib_api_status_t         status;\r
371         ib_pnp_req_t            pnp_req;\r
372         \r
373         IPOIB_ENTER( IPOIB_DBG_INIT );\r
374 \r
375         CL_ASSERT( !p_adapter->h_pnp );\r
376         CL_ASSERT( !p_adapter->registering );\r
377 \r
378         p_adapter->registering = TRUE;\r
379 \r
380         /* Register for PNP events. */\r
381         cl_memclr( &pnp_req, sizeof(pnp_req) );\r
382         pnp_req.pnp_class = IB_PNP_PORT | flags;\r
383         /*\r
384          * Context is the cl_obj of the adapter to allow passing cl_obj_deref\r
385          * to ib_dereg_pnp.\r
386          */\r
387         pnp_req.pnp_context = &p_adapter->obj;\r
388         pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;\r
389         status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
390         if( status != IB_SUCCESS )\r
391         {\r
392                 p_adapter->registering = FALSE;\r
393                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
394                         ("ib_reg_pnp returned %s\n", \r
395                         p_adapter->p_ifc->get_err_str( status )) );\r
396                 return status;\r
397         }\r
398         /*\r
399          * Reference the adapter on behalf of the PNP registration.\r
400          * This allows the destruction to block until the PNP deregistration\r
401          * completes.\r
402          */\r
403         cl_obj_ref( &p_adapter->obj );\r
404 \r
405         IPOIB_EXIT( IPOIB_DBG_INIT );\r
406         return status;\r
407 }\r
408 \r
409 \r
410 static void\r
411 __adapter_destroying(\r
412         IN                              cl_obj_t* const                         p_obj )\r
413 {\r
414         ipoib_adapter_t         *p_adapter;\r
415         KLOCK_QUEUE_HANDLE      hdl;\r
416 \r
417         IPOIB_ENTER( IPOIB_DBG_INIT );\r
418 \r
419         p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
420 \r
421         /*\r
422          * The adapter's object will be dereferenced when the deregistration\r
423          * completes.  No need to lock here since all PnP related API calls\r
424          * are driven by NDIS (via the Init/Reset/Destroy paths).\r
425          */\r
426         if( p_adapter->h_pnp )\r
427         {\r
428                 p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, cl_obj_deref );\r
429                 p_adapter->h_pnp = NULL;\r
430         }\r
431 \r
432         if( p_adapter->packet_filter )\r
433         {\r
434                 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
435                 cl_obj_lock( &p_adapter->obj );\r
436 \r
437                 ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
438                 cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry );\r
439 \r
440                 p_adapter->packet_filter = 0;\r
441 \r
442                 cl_obj_unlock( &p_adapter->obj );\r
443                 KeReleaseInStackQueuedSpinLock( &hdl );\r
444         }\r
445 \r
446         IPOIB_EXIT( IPOIB_DBG_INIT );\r
447 }\r
448 \r
449 \r
450 static void\r
451 __adapter_free(\r
452         IN                              cl_obj_t* const                         p_obj )\r
453 {\r
454         ipoib_adapter_t *p_adapter;\r
455 \r
456         IPOIB_ENTER( IPOIB_DBG_INIT );\r
457 \r
458         p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
459 \r
460         if( p_adapter->p_ifc )\r
461         {\r
462                 if( p_adapter->h_al )\r
463                         p_adapter->p_ifc->close_al( p_adapter->h_al );\r
464 \r
465                 cl_free( p_adapter->p_ifc );\r
466         }\r
467 \r
468         cl_vector_destroy( &p_adapter->ip_vector );\r
469         cl_qpool_destroy( &p_adapter->item_pool );\r
470         cl_spinlock_destroy( &p_adapter->recv_stat_lock );\r
471         cl_spinlock_destroy( &p_adapter->send_stat_lock );\r
472         cl_obj_deinit( p_obj );\r
473 \r
474         cl_perf_destroy( &p_adapter->perf, TRUE );\r
475 \r
476         cl_free( p_adapter );\r
477 \r
478         IPOIB_EXIT( IPOIB_DBG_INIT );\r
479 }\r
480 \r
481 \r
482 static ib_api_status_t\r
483 __ipoib_pnp_cb(\r
484         IN                              ib_pnp_rec_t                            *p_pnp_rec )\r
485 {\r
486         ib_api_status_t         status;\r
487         ipoib_adapter_t         *p_adapter;\r
488         ipoib_port_t            *p_port;\r
489         ib_pnp_event_t          old_state;\r
490         ib_pnp_port_rec_t       *p_port_rec;\r
491 \r
492         IPOIB_ENTER( IPOIB_DBG_PNP );\r
493 \r
494         CL_ASSERT( p_pnp_rec );\r
495 \r
496         p_adapter =\r
497                 PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );\r
498 \r
499         CL_ASSERT( p_adapter );\r
500 \r
501         /* Synchronize with destruction */\r
502         KeWaitForMutexObject(\r
503                 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
504         cl_obj_lock( &p_adapter->obj );\r
505         old_state = p_adapter->state;\r
506         cl_obj_unlock( &p_adapter->obj );\r
507         if( old_state == IB_PNP_PORT_REMOVE )\r
508         {\r
509                 KeReleaseMutex( &p_adapter->mutex, FALSE );\r
510                 IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
511                         ("Aborting - Adapter destroying.\n") );\r
512                 return IB_NOT_DONE;\r
513         }\r
514 \r
515         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
516                 ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
517                 p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
518 \r
519         p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec;\r
520 \r
521         switch( p_pnp_rec->pnp_event )\r
522         {\r
523         case IB_PNP_PORT_ADD:\r
524                 CL_ASSERT( !p_pnp_rec->context );\r
525                 /* Only process our port GUID. */\r
526                 if( p_pnp_rec->guid != p_adapter->guids.port_guid )\r
527                 {\r
528                         status = IB_NOT_DONE;\r
529                         break;\r
530                 }\r
531 \r
532                 /* Don't process if we're destroying. */\r
533                 if( p_adapter->obj.state == CL_DESTROYING )\r
534                 {\r
535                         status = IB_NOT_DONE;\r
536                         break;\r
537                 }\r
538 \r
539                 CL_ASSERT( !p_adapter->p_port );\r
540                 /* Allocate all IB resources. */\r
541                 cl_obj_lock( &p_adapter->obj );\r
542                 p_adapter->state = IB_PNP_PORT_ADD;\r
543                 cl_obj_unlock( &p_adapter->obj );\r
544                 status = ipoib_create_port( p_adapter, p_port_rec, &p_port );\r
545                 cl_obj_lock( &p_adapter->obj );\r
546                 if( status != IB_SUCCESS )\r
547                 {\r
548                         p_adapter->state = old_state;\r
549                         cl_obj_unlock( &p_adapter->obj );\r
550                         p_adapter->hung = TRUE;\r
551                         break;\r
552                 }\r
553 \r
554                 p_pnp_rec->context = p_port;\r
555 \r
556                 p_adapter->p_port = p_port;\r
557                 cl_obj_unlock( &p_adapter->obj );\r
558                 break;\r
559 \r
560         case IB_PNP_PORT_REMOVE:\r
561                 /* Release all IB resources. */\r
562                 CL_ASSERT( p_pnp_rec->context );\r
563 \r
564                 cl_obj_lock( &p_adapter->obj );\r
565                 p_adapter->state = IB_PNP_PORT_REMOVE;\r
566                 p_port = p_adapter->p_port;\r
567                 p_adapter->p_port = NULL;\r
568                 cl_obj_unlock( &p_adapter->obj );\r
569                 ipoib_port_destroy( p_port );\r
570                 p_pnp_rec->context = NULL;\r
571                 status = IB_SUCCESS;\r
572                 break;\r
573 \r
574         case IB_PNP_PORT_ACTIVE:\r
575                 /* Join multicast groups and put QP in RTS. */\r
576                 CL_ASSERT( p_pnp_rec->context );\r
577 \r
578                 cl_obj_lock( &p_adapter->obj );\r
579                 p_adapter->state = IB_PNP_PORT_INIT;\r
580                 cl_obj_unlock( &p_adapter->obj );\r
581                 ipoib_port_up( p_adapter->p_port, p_port_rec );\r
582 \r
583                 status = IB_SUCCESS;\r
584                 break;\r
585 \r
586         case IB_PNP_PORT_ARMED:\r
587                 status = IB_SUCCESS;\r
588                 break;\r
589 \r
590         case IB_PNP_PORT_INIT:\r
591                 /*\r
592                  * Init could happen if the SM brings the port down\r
593                  * without changing the physical link.\r
594                  */\r
595         case IB_PNP_PORT_DOWN:\r
596                 CL_ASSERT( p_pnp_rec->context );\r
597 \r
598                 cl_obj_lock( &p_adapter->obj );\r
599                 old_state = p_adapter->state;\r
600                 p_adapter->state = IB_PNP_PORT_DOWN;\r
601                 cl_obj_unlock( &p_adapter->obj );\r
602                 status = IB_SUCCESS;\r
603 \r
604                 if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN )\r
605                 {\r
606                         NdisMIndicateStatus( p_adapter->h_adapter,\r
607                                 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );\r
608                         NdisMIndicateStatusComplete( p_adapter->h_adapter );\r
609 \r
610                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
611                                 ("Link DOWN!\n") );\r
612 \r
613                         ipoib_port_down( p_adapter->p_port );\r
614                 }\r
615                 break;\r
616 \r
617         case IB_PNP_REG_COMPLETE:\r
618                 if( p_adapter->registering )\r
619                 {\r
620                         p_adapter->registering = FALSE;\r
621                         cl_obj_lock( &p_adapter->obj );\r
622                         old_state = p_adapter->state;\r
623                         cl_obj_unlock( &p_adapter->obj );\r
624 \r
625                         if( old_state == IB_PNP_PORT_DOWN )\r
626                         {\r
627                                 /* If we were initializing, we might have pended some OIDs. */\r
628                                 ipoib_resume_oids( p_adapter );\r
629                                 NdisMIndicateStatus( p_adapter->h_adapter,\r
630                                         NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );\r
631                                 NdisMIndicateStatusComplete( p_adapter->h_adapter );\r
632                         }\r
633                 }\r
634 \r
635                 if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT )\r
636                 {\r
637                         p_adapter->reset = FALSE;\r
638                         NdisMResetComplete(\r
639                                 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
640                 }\r
641                 status = IB_SUCCESS;\r
642                 break;\r
643 \r
644         default:\r
645                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
646                         ("IPOIB: Received unhandled PnP event 0x%x (%s)\n",\r
647                         p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
648                 /* Fall through. */\r
649         case IB_PNP_PKEY_CHANGE:\r
650         case IB_PNP_SM_CHANGE:\r
651         case IB_PNP_GID_CHANGE:\r
652         case IB_PNP_LID_CHANGE:\r
653                 status = IB_SUCCESS;\r
654 \r
655                 /* We ignore this event if the link is not active. */\r
656                 if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE )\r
657                         break;\r
658 \r
659                 cl_obj_lock( &p_adapter->obj );\r
660                 old_state = p_adapter->state;\r
661                 switch( old_state )\r
662                 {\r
663                 case IB_PNP_PORT_DOWN:\r
664                         p_adapter->state = IB_PNP_PORT_INIT;\r
665                         break;\r
666 \r
667                 default:\r
668                         p_adapter->state = IB_PNP_PORT_DOWN;\r
669                 }\r
670                 cl_obj_unlock( &p_adapter->obj );\r
671                 \r
672                 if( p_adapter->registering )\r
673                         break;\r
674 \r
675                 switch( old_state )\r
676                 {\r
677                 case IB_PNP_PORT_ACTIVE:\r
678                 case IB_PNP_PORT_INIT:\r
679                         NdisMIndicateStatus( p_adapter->h_adapter,\r
680                                 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );\r
681                         NdisMIndicateStatusComplete( p_adapter->h_adapter );\r
682 \r
683                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
684                                 ("Link DOWN!\n") );\r
685 \r
686                         ipoib_port_down( p_adapter->p_port );\r
687                         /* Fall through. */\r
688 \r
689                 case IB_PNP_PORT_DOWN:\r
690                         cl_obj_lock( &p_adapter->obj );\r
691                         p_adapter->state = IB_PNP_PORT_INIT;\r
692                         cl_obj_unlock( &p_adapter->obj );\r
693                         ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );\r
694                 }\r
695                 break;\r
696         }\r
697 \r
698         KeReleaseMutex( &p_adapter->mutex, FALSE );\r
699 \r
700         IPOIB_EXIT( IPOIB_DBG_PNP );\r
701         return status;\r
702 }\r
703 \r
704 \r
705 /* Joins/leaves mcast groups based on currently programmed mcast MACs. */\r
706 void\r
707 ipoib_refresh_mcast(\r
708         IN                              ipoib_adapter_t* const          p_adapter,\r
709         IN                              mac_addr_t* const                       p_mac_array,\r
710         IN              const   uint8_t                                         num_macs )\r
711 {\r
712         uint8_t                         i, j;\r
713         ipoib_port_t            *p_port = NULL;\r
714 \r
715         IPOIB_ENTER( IPOIB_DBG_MCAST );\r
716         cl_obj_lock( &p_adapter->obj );\r
717         if( p_adapter->state == IB_PNP_PORT_ACTIVE )\r
718         {\r
719                 p_port = p_adapter->p_port;\r
720                 cl_obj_ref( &p_port->obj );\r
721         }\r
722         cl_obj_unlock( &p_adapter->obj );\r
723 \r
724         if( p_port )\r
725         {\r
726                 /* Purge old entries. */\r
727                 for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
728                 {\r
729                         for( j = 0; j < num_macs; j++ )\r
730                         {\r
731                                 if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],\r
732                                         sizeof(mac_addr_t) ) )\r
733                                 {\r
734                                         break;\r
735                                 }\r
736                         }\r
737                         if( j != num_macs )\r
738                                 continue;\r
739 \r
740                         ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );\r
741                 }\r
742 \r
743                 /* Add new entries */\r
744                 for( i = 0; i < num_macs; i++ )\r
745                 {\r
746                         for( j = 0; j < p_adapter->mcast_array_size; j++ )\r
747                         {\r
748                                 if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],\r
749                                         sizeof(mac_addr_t) ) )\r
750                                 {\r
751                                         break;\r
752                                 }\r
753                         }\r
754 \r
755                         if( j != p_adapter->mcast_array_size )\r
756                                 continue;\r
757 \r
758                         ipoib_port_join_mcast( p_port, p_mac_array[i] );\r
759                 }\r
760         }\r
761 \r
762         /* Copy the MAC array. */\r
763         NdisMoveMemory( p_adapter->mcast_array, p_mac_array,\r
764                 num_macs * sizeof(mac_addr_t) );\r
765         p_adapter->mcast_array_size = num_macs;\r
766 \r
767         if( p_port )\r
768                 cl_obj_deref( &p_port->obj );\r
769 \r
770         IPOIB_EXIT( IPOIB_DBG_MCAST );\r
771 }\r
772 \r
773 \r
774 ib_api_status_t\r
775 ipoib_reset_adapter(\r
776         IN                              ipoib_adapter_t* const          p_adapter )\r
777 {\r
778         ib_api_status_t         status;\r
779         ib_pnp_handle_t         h_pnp;\r
780 \r
781         IPOIB_ENTER( IPOIB_DBG_INIT );\r
782 \r
783         if( p_adapter->reset )\r
784                 return IB_INVALID_STATE;\r
785 \r
786         p_adapter->hung = FALSE;\r
787         p_adapter->reset = TRUE;\r
788 \r
789         if( p_adapter->h_pnp )\r
790         {\r
791                 h_pnp = p_adapter->h_pnp;\r
792                 p_adapter->h_pnp  = NULL;\r
793                 status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg );\r
794                 if( status == IB_SUCCESS )\r
795                         status = IB_NOT_DONE;\r
796         }\r
797         else\r
798         {\r
799                 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
800                 if( status == IB_SUCCESS )\r
801                         p_adapter->hung = FALSE;\r
802         }\r
803 \r
804         IPOIB_EXIT( IPOIB_DBG_INIT );\r
805         return status;\r
806 }\r
807 \r
808 \r
809 static void\r
810 __ipoib_pnp_dereg(\r
811         IN                              void*                                           context )\r
812 {\r
813         ipoib_adapter_t*        p_adapter;\r
814         ipoib_port_t*           p_port;\r
815         ib_api_status_t         status;\r
816         ib_pnp_event_t          state;\r
817 \r
818         IPOIB_ENTER( IPOIB_DBG_INIT );\r
819 \r
820         p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );\r
821 \r
822         /* Synchronize with destruction */\r
823         KeWaitForMutexObject(\r
824                 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
825 \r
826         cl_obj_lock( &p_adapter->obj );\r
827 \r
828         CL_ASSERT( !p_adapter->h_pnp );\r
829 \r
830         if( p_adapter->state != IB_PNP_PORT_REMOVE )\r
831                 p_adapter->state = IB_PNP_PORT_ADD;\r
832 \r
833         state = p_adapter->state;\r
834 \r
835         /* Destroy the current port instance if it still exists. */\r
836         p_port = p_adapter->p_port;\r
837         p_adapter->p_port = NULL;\r
838         cl_obj_unlock( &p_adapter->obj );\r
839 \r
840         if( p_port )\r
841                 ipoib_port_destroy( p_port );\r
842 \r
843         if( state != IB_PNP_PORT_REMOVE )\r
844         {\r
845                 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
846                 if( status != IB_SUCCESS )\r
847                 {\r
848                         p_adapter->reset = FALSE;\r
849                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
850                                 ("__ipoib_pnp_reg returned %s\n",\r
851                                 p_adapter->p_ifc->get_err_str( status )) );\r
852                         NdisMResetComplete( \r
853                                 p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );\r
854                 }\r
855         }\r
856         else\r
857         {\r
858                 p_adapter->reset = FALSE;\r
859                 NdisMResetComplete(\r
860                         p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
861                 status = IB_SUCCESS;\r
862         }\r
863 \r
864         /* Dereference the adapter since the previous registration is now gone. */\r
865         cl_obj_deref( &p_adapter->obj );\r
866 \r
867         KeReleaseMutex( &p_adapter->mutex, FALSE );\r
868 \r
869         IPOIB_EXIT( IPOIB_DBG_INIT );\r
870 }\r
871 \r
872 \r
873 void\r
874 ipoib_set_rate(\r
875         IN                              ipoib_adapter_t* const          p_adapter,\r
876         IN              const   uint8_t                                         link_width, \r
877         IN              const   uint8_t                                         link_speed )\r
878 {\r
879         uint32_t        rate;\r
880 \r
881         IPOIB_ENTER( IPOIB_DBG_INIT );\r
882 \r
883         /* Set the link speed based on the IB link speed (1x vs 4x, etc). */\r
884         switch( link_speed )\r
885         {\r
886         case IB_LINK_SPEED_ACTIVE_2_5:\r
887                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
888                         ("Link speed is 2.5Gs\n") );\r
889                 rate = IB_LINK_SPEED_ACTIVE_2_5;\r
890                 break;\r
891 \r
892         case IB_LINK_SPEED_ACTIVE_5:\r
893                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
894                         ("Link speed is 5G\n") );\r
895                 rate = IB_LINK_SPEED_ACTIVE_5;\r
896                 break;\r
897 \r
898         case IB_LINK_SPEED_ACTIVE_10:\r
899                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
900                         ("Link speed is 10G\n") );\r
901                 rate = IB_LINK_SPEED_ACTIVE_10;\r
902                 break;\r
903 \r
904         default:\r
905                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
906                         ("Invalid link speed %d.\n", link_speed) );\r
907                 rate = 0;\r
908         }\r
909 \r
910         switch( link_width )\r
911         {\r
912         case IB_LINK_WIDTH_ACTIVE_1X:\r
913                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
914                         ("Link width is 1X\n") );\r
915                 rate *= ONE_X_IN_100BPS;\r
916                 break;\r
917 \r
918         case IB_LINK_WIDTH_ACTIVE_4X:\r
919                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
920                         ("Link width is 4X\n") );\r
921                 rate *= FOUR_X_IN_100BPS;\r
922                 break;\r
923 \r
924         case IB_LINK_WIDTH_ACTIVE_12X:\r
925                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
926                         ("Link width is 12X\n") );\r
927                 rate *= TWELVE_X_IN_100BPS;\r
928                 break;\r
929 \r
930         default:\r
931                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
932                         ("Invalid link rate (%d).\n", link_width) );\r
933                 rate = 0;\r
934         }\r
935 \r
936         p_adapter->rate = rate;\r
937         IPOIB_EXIT( IPOIB_DBG_INIT );\r
938 }\r
939 \r
940 \r
941 void\r
942 ipoib_set_active(\r
943         IN                              ipoib_adapter_t* const          p_adapter )\r
944 {\r
945         ib_pnp_event_t  old_state;\r
946         uint8_t                 i;\r
947 \r
948         IPOIB_ENTER( IPOIB_DBG_INIT );\r
949 \r
950         cl_obj_lock( &p_adapter->obj );\r
951         old_state = p_adapter->state;\r
952 \r
953         /* Change the state to indicate that we are now connected and live. */\r
954         if( old_state != IB_PNP_PORT_REMOVE )\r
955                 p_adapter->state = IB_PNP_PORT_ACTIVE;\r
956 \r
957         cl_obj_unlock( &p_adapter->obj );\r
958 \r
959         /*\r
960          * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
961          * complete it now.\r
962          */\r
963         switch( old_state )\r
964         {\r
965         case IB_PNP_PORT_ADD:\r
966                 ipoib_reg_addrs( p_adapter );\r
967                 /* Fall through. */\r
968 \r
969         case IB_PNP_PORT_REMOVE:\r
970                 ipoib_resume_oids( p_adapter );\r
971                 break;\r
972 \r
973         default:\r
974                 /* Join all programmed multicast groups. */\r
975                 for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
976                 {\r
977                         ipoib_port_join_mcast(\r
978                                 p_adapter->p_port, p_adapter->mcast_array[i] );\r
979                 }\r
980 \r
981                 /* Register all existing addresses. */\r
982                 ipoib_reg_addrs( p_adapter );\r
983 \r
984                 ipoib_resume_oids( p_adapter );\r
985 \r
986                 /*\r
987                  * Now that we're in the broadcast group, notify that\r
988                  * we have a link.\r
989                  */\r
990                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Link UP!\n") );\r
991                 NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
992                         EVENT_IPOIB_PORT_UP + (p_adapter->rate/ONE_X_IN_100BPS),\r
993                         1, p_adapter->rate );\r
994 \r
995                 if( !p_adapter->reset )\r
996                 {\r
997                         NdisMIndicateStatus( p_adapter->h_adapter, NDIS_STATUS_MEDIA_CONNECT,\r
998                                 NULL, 0 );\r
999                         NdisMIndicateStatusComplete( p_adapter->h_adapter );\r
1000                 }\r
1001         }\r
1002 \r
1003         if( p_adapter->reset )\r
1004         {\r
1005                 p_adapter->reset = FALSE;\r
1006                 NdisMResetComplete(\r
1007                         p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
1008         }\r
1009 \r
1010         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1011 }\r
1012 \r
1013 \r
1014 /*\r
1015  * If something goes wrong after the port goes active, e.g.\r
1016  *      - PortInfo query failure\r
1017  *      - MC Join timeout\r
1018  *      - etc\r
1019  * Mark the port state as down, resume any pended OIDS, etc.\r
1020  */\r
1021 void\r
1022 ipoib_set_inactive(\r
1023         IN                              ipoib_adapter_t* const          p_adapter )\r
1024 {\r
1025         ib_pnp_event_t  old_state;\r
1026 \r
1027         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1028 \r
1029         cl_obj_lock( &p_adapter->obj );\r
1030         old_state = p_adapter->state;\r
1031         if( old_state != IB_PNP_PORT_REMOVE )\r
1032                 p_adapter->state = IB_PNP_PORT_DOWN;\r
1033         cl_obj_unlock( &p_adapter->obj );\r
1034 \r
1035         /*\r
1036          * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
1037          * complete it now.\r
1038          */\r
1039         if( old_state == IB_PNP_PORT_INIT )\r
1040         {\r
1041                 NdisMIndicateStatus( p_adapter->h_adapter,\r
1042                         NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );\r
1043                 NdisMIndicateStatusComplete( p_adapter->h_adapter );\r
1044 \r
1045                 ipoib_resume_oids( p_adapter );\r
1046         }\r
1047 \r
1048         if( p_adapter->reset )\r
1049         {\r
1050                 p_adapter->reset = FALSE;\r
1051                 NdisMResetComplete(\r
1052                         p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
1053         }\r
1054 \r
1055         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1056 }\r
1057 \r
1058 \r
1059 NDIS_STATUS\r
1060 ipoib_get_recv_stat(\r
1061         IN                              ipoib_adapter_t* const          p_adapter,\r
1062         IN              const   ip_stat_sel_t                           stat_sel,\r
1063         IN                              pending_oid_t* const            p_oid_info )\r
1064 {\r
1065         uint64_t        stat;\r
1066 \r
1067         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1068 \r
1069         CL_ASSERT( p_adapter );\r
1070 \r
1071         cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
1072         switch( stat_sel )\r
1073         {\r
1074         case IP_STAT_SUCCESS:\r
1075                 stat = p_adapter->recv_stats.comp.success;\r
1076                 break;\r
1077 \r
1078         case IP_STAT_ERROR:\r
1079                 stat = p_adapter->recv_stats.comp.error;\r
1080                 break;\r
1081 \r
1082         case IP_STAT_DROPPED:\r
1083                 stat = p_adapter->recv_stats.comp.dropped;\r
1084                 break;\r
1085 \r
1086         case IP_STAT_UCAST_BYTES:\r
1087                 stat = p_adapter->recv_stats.ucast.bytes;\r
1088                 break;\r
1089 \r
1090         case IP_STAT_UCAST_FRAMES:\r
1091                 stat = p_adapter->recv_stats.ucast.frames;\r
1092                 break;\r
1093 \r
1094         case IP_STAT_BCAST_BYTES:\r
1095                 stat = p_adapter->recv_stats.bcast.bytes;\r
1096                 break;\r
1097 \r
1098         case IP_STAT_BCAST_FRAMES:\r
1099                 stat = p_adapter->recv_stats.bcast.frames;\r
1100                 break;\r
1101 \r
1102         case IP_STAT_MCAST_BYTES:\r
1103                 stat = p_adapter->recv_stats.mcast.bytes;\r
1104                 break;\r
1105 \r
1106         case IP_STAT_MCAST_FRAMES:\r
1107                 stat = p_adapter->recv_stats.mcast.frames;\r
1108                 break;\r
1109 \r
1110         default:\r
1111                 stat = 0;\r
1112         }\r
1113         cl_spinlock_release( &p_adapter->recv_stat_lock );\r
1114 \r
1115         *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
1116 \r
1117         if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
1118         {\r
1119                 *((uint64_t*)p_oid_info->p_buf) = stat;\r
1120                 *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
1121         }\r
1122         else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
1123         {\r
1124                 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
1125                 *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
1126         }\r
1127         else\r
1128         {\r
1129                 *p_oid_info->p_bytes_used = 0;\r
1130                 IPOIB_EXIT( IPOIB_DBG_STAT );\r
1131                 return NDIS_STATUS_INVALID_LENGTH;\r
1132         }\r
1133 \r
1134         IPOIB_EXIT( IPOIB_DBG_STAT );\r
1135         return NDIS_STATUS_SUCCESS;\r
1136 }\r
1137 \r
1138 \r
1139 void\r
1140 ipoib_inc_recv_stat(\r
1141         IN                              ipoib_adapter_t* const          p_adapter,\r
1142         IN              const   ip_stat_sel_t                           stat_sel,\r
1143         IN              const   size_t                                          bytes OPTIONAL )\r
1144 {\r
1145         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1146 \r
1147         cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
1148         switch( stat_sel )\r
1149         {\r
1150         case IP_STAT_ERROR:\r
1151                 p_adapter->recv_stats.comp.error++;\r
1152                 break;\r
1153 \r
1154         case IP_STAT_DROPPED:\r
1155                 p_adapter->recv_stats.comp.dropped++;\r
1156                 break;\r
1157 \r
1158         case IP_STAT_UCAST_BYTES:\r
1159         case IP_STAT_UCAST_FRAMES:\r
1160                 p_adapter->recv_stats.comp.success++;\r
1161                 p_adapter->recv_stats.ucast.frames++;\r
1162                 p_adapter->recv_stats.ucast.bytes += bytes;\r
1163                 break;\r
1164 \r
1165         case IP_STAT_BCAST_BYTES:\r
1166         case IP_STAT_BCAST_FRAMES:\r
1167                 p_adapter->recv_stats.comp.success++;\r
1168                 p_adapter->recv_stats.bcast.frames++;\r
1169                 p_adapter->recv_stats.bcast.bytes += bytes;\r
1170                 break;\r
1171 \r
1172         case IP_STAT_MCAST_BYTES:\r
1173         case IP_STAT_MCAST_FRAMES:\r
1174                 p_adapter->recv_stats.comp.success++;\r
1175                 p_adapter->recv_stats.mcast.frames++;\r
1176                 p_adapter->recv_stats.mcast.bytes += bytes;\r
1177                 break;\r
1178 \r
1179         default:\r
1180                 break;\r
1181         }\r
1182         cl_spinlock_release( &p_adapter->recv_stat_lock );\r
1183 \r
1184         IPOIB_EXIT( IPOIB_DBG_STAT );\r
1185 }\r
1186 \r
1187 NDIS_STATUS\r
1188 ipoib_get_send_stat(\r
1189         IN                              ipoib_adapter_t* const          p_adapter,\r
1190         IN              const   ip_stat_sel_t                           stat_sel,\r
1191         IN                              pending_oid_t* const            p_oid_info )\r
1192 {\r
1193         uint64_t        stat;\r
1194 \r
1195         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1196 \r
1197         CL_ASSERT( p_adapter );\r
1198 \r
1199         cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
1200         switch( stat_sel )\r
1201         {\r
1202         case IP_STAT_SUCCESS:\r
1203                 stat = p_adapter->send_stats.comp.success;\r
1204                 break;\r
1205 \r
1206         case IP_STAT_ERROR:\r
1207                 stat = p_adapter->send_stats.comp.error;\r
1208                 break;\r
1209 \r
1210         case IP_STAT_DROPPED:\r
1211                 stat = p_adapter->send_stats.comp.dropped;\r
1212                 break;\r
1213 \r
1214         case IP_STAT_UCAST_BYTES:\r
1215                 stat = p_adapter->send_stats.ucast.bytes;\r
1216                 break;\r
1217 \r
1218         case IP_STAT_UCAST_FRAMES:\r
1219                 stat = p_adapter->send_stats.ucast.frames;\r
1220                 break;\r
1221 \r
1222         case IP_STAT_BCAST_BYTES:\r
1223                 stat = p_adapter->send_stats.bcast.bytes;\r
1224                 break;\r
1225 \r
1226         case IP_STAT_BCAST_FRAMES:\r
1227                 stat = p_adapter->send_stats.bcast.frames;\r
1228                 break;\r
1229 \r
1230         case IP_STAT_MCAST_BYTES:\r
1231                 stat = p_adapter->send_stats.mcast.bytes;\r
1232                 break;\r
1233 \r
1234         case IP_STAT_MCAST_FRAMES:\r
1235                 stat = p_adapter->send_stats.mcast.frames;\r
1236                 break;\r
1237 \r
1238         default:\r
1239                 stat = 0;\r
1240         }\r
1241         cl_spinlock_release( &p_adapter->send_stat_lock );\r
1242 \r
1243         *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
1244 \r
1245         if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
1246         {\r
1247                 *((uint64_t*)p_oid_info->p_buf) = stat;\r
1248                 *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
1249         }\r
1250         else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
1251         {\r
1252                 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
1253                 *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
1254         }\r
1255         else\r
1256         {\r
1257                 *p_oid_info->p_bytes_used = 0;\r
1258                 IPOIB_EXIT( IPOIB_DBG_STAT );\r
1259                 return NDIS_STATUS_INVALID_LENGTH;\r
1260         }\r
1261 \r
1262         IPOIB_EXIT( IPOIB_DBG_STAT );\r
1263         return NDIS_STATUS_SUCCESS;\r
1264 }\r
1265 \r
1266 \r
1267 void\r
1268 ipoib_inc_send_stat(\r
1269         IN                              ipoib_adapter_t* const          p_adapter,\r
1270         IN              const   ip_stat_sel_t                           stat_sel,\r
1271         IN              const   size_t                                          bytes OPTIONAL )\r
1272 {\r
1273         IPOIB_ENTER( IPOIB_DBG_STAT );\r
1274 \r
1275         cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
1276         switch( stat_sel )\r
1277         {\r
1278         case IP_STAT_ERROR:\r
1279                 p_adapter->send_stats.comp.error++;\r
1280                 break;\r
1281 \r
1282         case IP_STAT_DROPPED:\r
1283                 p_adapter->send_stats.comp.dropped++;\r
1284                 break;\r
1285 \r
1286         case IP_STAT_UCAST_BYTES:\r
1287         case IP_STAT_UCAST_FRAMES:\r
1288                 p_adapter->send_stats.comp.success++;\r
1289                 p_adapter->send_stats.ucast.frames++;\r
1290                 p_adapter->send_stats.ucast.bytes += bytes;\r
1291                 break;\r
1292 \r
1293         case IP_STAT_BCAST_BYTES:\r
1294         case IP_STAT_BCAST_FRAMES:\r
1295                 p_adapter->send_stats.comp.success++;\r
1296                 p_adapter->send_stats.bcast.frames++;\r
1297                 p_adapter->send_stats.bcast.bytes += bytes;\r
1298                 break;\r
1299 \r
1300         case IP_STAT_MCAST_BYTES:\r
1301         case IP_STAT_MCAST_FRAMES:\r
1302                 p_adapter->send_stats.comp.success++;\r
1303                 p_adapter->send_stats.mcast.frames++;\r
1304                 p_adapter->send_stats.mcast.bytes += bytes;\r
1305                 break;\r
1306 \r
1307         default:\r
1308                 break;\r
1309         }\r
1310         cl_spinlock_release( &p_adapter->send_stat_lock );\r
1311 \r
1312         IPOIB_EXIT( IPOIB_DBG_STAT );\r
1313 }\r