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