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