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