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