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