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