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