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