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