2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\r
7 * Redistribution and use in source and binary forms, with or
\r
8 * without modification, are permitted provided that the following
\r
9 * conditions are met:
\r
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\r
15 * - Redistributions in binary form must reproduce the above
\r
16 * copyright notice, this list of conditions and the following
\r
17 * disclaimer in the documentation and/or other materials
\r
18 * provided with the distribution.
\r
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
34 #include "ipoib_adapter.h"
\r
35 #include "ipoib_port.h"
\r
36 #include "ipoib_driver.h"
\r
37 #include "ipoib_debug.h"
\r
40 #define ITEM_POOL_START 16
\r
41 #define ITEM_POOL_GROW 16
\r
44 /* IB Link speeds in 100bps */
\r
45 #define ONE_X_IN_100BPS 25000000
\r
46 #define FOUR_X_IN_100BPS 100000000
\r
47 #define TWELVE_X_IN_100BPS 300000000
\r
53 IN ipoib_adapter_t* const p_adapter );
\r
56 static ib_api_status_t
\r
58 IN ipoib_adapter_t* const p_adapter );
\r
62 __adapter_destroying(
\r
63 IN cl_obj_t* const p_obj );
\r
68 IN cl_obj_t* const p_obj );
\r
73 IN cl_obj_t* const p_obj );
\r
76 static ib_api_status_t
\r
78 IN ipoib_adapter_t* const p_adapter,
\r
79 IN ib_pnp_class_t flags );
\r
87 static ib_api_status_t
\r
89 IN ib_pnp_rec_t *p_pnp_rec );
\r
94 IN ipoib_adapter_t* const p_adapter );
\r
99 IN ipoib_adapter_t* const p_adapter );
\r
102 /* Leaves all mcast groups when port goes down. */
\r
105 IN ipoib_port_t* const p_port );
\r
108 ipoib_get_adapter_guids(
\r
109 IN NDIS_HANDLE* const h_adapter,
\r
110 IN OUT ipoib_adapter_t *p_adapter );
\r
113 ipoib_get_adapter_params(
\r
114 IN NDIS_HANDLE* const wrapper_config_context,
\r
115 OUT ipoib_params_t* const p_params );
\r
118 /* Implementation */
\r
120 ipoib_create_adapter(
\r
121 IN NDIS_HANDLE wrapper_config_context,
\r
122 IN void* const h_adapter,
\r
123 OUT ipoib_adapter_t** const pp_adapter )
\r
125 ipoib_adapter_t *p_adapter;
\r
126 ib_api_status_t status;
\r
127 cl_status_t cl_status;
\r
129 KLOCK_QUEUE_HANDLE hdl;
\r
131 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
133 p_adapter = cl_zalloc( sizeof(ipoib_adapter_t) );
\r
136 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
137 ("Failed to allocate ipoib_adapter_t (%d bytes)",
\r
138 sizeof(ipoib_adapter_t)) );
\r
139 return IB_INSUFFICIENT_MEMORY;
\r
142 adapter_construct( p_adapter );
\r
144 p_adapter->h_adapter = h_adapter;
\r
146 p_adapter->p_ifc = cl_zalloc( sizeof(ib_al_ifc_t) );
\r
147 if( !p_adapter->p_ifc )
\r
149 __adapter_free( &p_adapter->obj );
\r
150 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
151 ("ipoib_create_adapter failed to alloc ipoib_ifc_t % bytes\n",
\r
152 sizeof(ib_al_ifc_t)) );
\r
153 return IB_INSUFFICIENT_MEMORY;
\r
156 /* Get the CA and port GUID from the bus driver. */
\r
157 status = ipoib_get_adapter_guids( h_adapter, p_adapter );
\r
158 if( status != NDIS_STATUS_SUCCESS )
\r
160 __adapter_free( &p_adapter->obj );
\r
161 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
162 ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );
\r
166 port_num = IPOIB_GET_PORT_NUM_FROM_GUID(p_adapter->guids.port_guid);
\r
168 IPOIB_TRACE( IPOIB_DBG_INFO,
\r
169 ("Port %d initializing\n", port_num) );
\r
171 /* Read configuration parameters. */
\r
172 status = ipoib_get_adapter_params( wrapper_config_context,
\r
173 &p_adapter->params );
\r
174 if( status != NDIS_STATUS_SUCCESS )
\r
176 __adapter_free( &p_adapter->obj );
\r
177 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
178 ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );
\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
186 __adapter_free( &p_adapter->obj );
\r
187 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
188 ("cl_obj_init returned %s\n", cl_status_text[cl_status]) );
\r
192 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
\r
193 InsertHeadList( &g_ipoib.adapter_list, &p_adapter->entry );
\r
194 KeReleaseInStackQueuedSpinLock( &hdl );
\r
196 status = adapter_init( p_adapter );
\r
197 if( status != IB_SUCCESS )
\r
199 cl_obj_destroy( &p_adapter->obj );
\r
200 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
201 ("adapter_init returned %s.\n",
\r
202 p_adapter->p_ifc->get_err_str( status )) );
\r
206 *pp_adapter = p_adapter;
\r
208 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
214 ipoib_start_adapter(
\r
215 IN ipoib_adapter_t* const p_adapter )
\r
217 ib_api_status_t status;
\r
219 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
221 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_SYNC );
\r
223 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
229 ipoib_destroy_adapter(
\r
230 IN ipoib_adapter_t* const p_adapter )
\r
232 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
234 CL_ASSERT( p_adapter );
\r
237 * Flag the adapter as being removed. We use the IB_PNP_CA_REMOVE state
\r
238 * for this purpose. Note that we protect this state change with both the
\r
239 * mutex and the lock. The mutex provides synchronization as a whole
\r
240 * between destruction and AL callbacks (PnP, Query, Destruction).
\r
241 * The lock provides protection
\r
243 cl_mutex_acquire( &p_adapter->mutex );
\r
244 cl_obj_lock( &p_adapter->obj );
\r
245 p_adapter->state = IB_PNP_PORT_REMOVE;
\r
246 cl_obj_unlock( &p_adapter->obj );
\r
249 * Clear the pointer to the port object since the object destruction
\r
250 * will cascade to child objects. This prevents potential duplicate
\r
251 * destruction (or worse, stale pointer usage).
\r
253 p_adapter->p_port = NULL;
\r
255 cl_mutex_release( &p_adapter->mutex );
\r
257 cl_obj_destroy( &p_adapter->obj );
\r
259 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
265 IN ipoib_adapter_t* const p_adapter )
\r
267 cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );
\r
268 cl_spinlock_construct( &p_adapter->send_stat_lock );
\r
269 cl_spinlock_construct( &p_adapter->recv_stat_lock );
\r
270 cl_qpool_construct( &p_adapter->item_pool );
\r
271 cl_mutex_construct( &p_adapter->mutex );
\r
272 cl_vector_construct( &p_adapter->ip_vector );
\r
274 cl_perf_construct( &p_adapter->perf );
\r
276 p_adapter->state = IB_PNP_PORT_ADD;
\r
277 p_adapter->rate = FOUR_X_IN_100BPS;
\r
281 static ib_api_status_t
\r
283 IN ipoib_adapter_t* const p_adapter )
\r
285 cl_status_t cl_status;
\r
286 ib_api_status_t status;
\r
288 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
290 cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );
\r
291 if( cl_status != CL_SUCCESS )
\r
293 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
294 ("cl_perf_init returned %s\n", cl_status_text[cl_status]) );
\r
298 cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );
\r
299 if( cl_status != CL_SUCCESS )
\r
301 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
302 ("cl_spinlock_init returned %s\n", cl_status_text[cl_status]) );
\r
306 cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );
\r
307 if( cl_status != CL_SUCCESS )
\r
309 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
310 ("cl_spinlock_init returned %s\n", cl_status_text[cl_status]) );
\r
314 cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,
\r
315 ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );
\r
316 if( cl_status != CL_SUCCESS )
\r
318 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
319 ("cl_qpool_init returned %s\n", cl_status_text[cl_status]) );
\r
323 cl_status = cl_mutex_init( &p_adapter->mutex );
\r
324 if( cl_status != CL_SUCCESS )
\r
326 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
327 ("cl_mutex_init returned %s\n", cl_status_text[cl_status]) );
\r
331 /* We manually manage the size and capacity of the vector. */
\r
332 cl_status = cl_vector_init( &p_adapter->ip_vector, 0,
\r
333 0, sizeof(net_address_item_t), NULL, NULL, p_adapter );
\r
334 if( cl_status != CL_SUCCESS )
\r
336 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
337 ("cl_vector_init for ip_vector returned %s\n",
\r
338 CL_STATUS_MSG(cl_status)) );
\r
342 /* Validate the port GUID and generate the MAC address. */
\r
344 ipoib_mac_from_guid( p_adapter->guids.port_guid, &p_adapter->mac );
\r
345 if( status != IB_SUCCESS )
\r
347 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
348 ("ipoib_mac_from_guid returned %s\n",
\r
349 p_adapter->p_ifc->get_err_str( status )) );
\r
354 status = p_adapter->p_ifc->open_al( &p_adapter->h_al );
\r
355 if( status != IB_SUCCESS )
\r
357 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
358 ("ib_open_al returned %s\n",
\r
359 p_adapter->p_ifc->get_err_str( status )) );
\r
363 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
368 static ib_api_status_t
\r
370 IN ipoib_adapter_t* const p_adapter,
\r
371 IN ib_pnp_class_t flags )
\r
373 ib_api_status_t status;
\r
374 ib_pnp_req_t pnp_req;
\r
376 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
378 CL_ASSERT( !p_adapter->h_pnp );
\r
380 /* Register for PNP events. */
\r
381 cl_memclr( &pnp_req, sizeof(pnp_req) );
\r
382 pnp_req.pnp_class = IB_PNP_PORT | flags;
\r
384 * Context is the cl_obj of the adapter to allow passing cl_obj_deref
\r
387 pnp_req.pnp_context = &p_adapter->obj;
\r
388 pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;
\r
389 status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );
\r
390 if( status != IB_SUCCESS )
\r
392 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
393 ("ib_reg_pnp returned %s\n",
\r
394 p_adapter->p_ifc->get_err_str( status )) );
\r
398 * Reference the adapter on behalf of the PNP registration.
\r
399 * This allows the destruction to block until the PNP deregistration
\r
402 cl_obj_ref( &p_adapter->obj );
\r
404 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
410 __adapter_destroying(
\r
411 IN cl_obj_t* const p_obj )
\r
413 ipoib_adapter_t *p_adapter;
\r
414 KLOCK_QUEUE_HANDLE hdl;
\r
416 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
418 p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );
\r
421 * The adapter's object will be dereferenced when the deregistration
\r
422 * completes. No need to lock here since all PnP related API calls
\r
423 * are driven by NDIS (via the Init/Reset/Destroy paths).
\r
425 if( p_adapter->h_pnp )
\r
427 p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, cl_obj_deref );
\r
428 p_adapter->h_pnp = NULL;
\r
431 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
\r
432 ASSERT( !IsListEmpty( &g_ipoib.adapter_list ) );
\r
433 RemoveEntryList( &p_adapter->entry );
\r
434 KeReleaseInStackQueuedSpinLock( &hdl );
\r
436 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
442 IN cl_obj_t* const p_obj )
\r
444 ipoib_adapter_t *p_adapter;
\r
446 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
448 p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );
\r
450 if( p_adapter->p_ifc )
\r
452 if( p_adapter->h_al )
\r
453 p_adapter->p_ifc->close_al( p_adapter->h_al );
\r
455 cl_free( p_adapter->p_ifc );
\r
458 cl_vector_destroy( &p_adapter->ip_vector );
\r
459 cl_qpool_destroy( &p_adapter->item_pool );
\r
460 cl_spinlock_destroy( &p_adapter->recv_stat_lock );
\r
461 cl_spinlock_destroy( &p_adapter->send_stat_lock );
\r
462 cl_mutex_destroy( &p_adapter->mutex );
\r
463 cl_obj_deinit( p_obj );
\r
465 cl_perf_destroy( &p_adapter->perf, TRUE );
\r
467 cl_free( p_adapter );
\r
469 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
473 static ib_api_status_t
\r
475 IN ib_pnp_rec_t *p_pnp_rec )
\r
477 ib_api_status_t status;
\r
478 ipoib_adapter_t *p_adapter;
\r
479 ib_pnp_event_t old_state;
\r
481 IPOIB_ENTER( IPOIB_DBG_PNP );
\r
483 CL_ASSERT( p_pnp_rec );
\r
486 PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );
\r
488 CL_ASSERT( p_adapter );
\r
490 /* Synchronize with destruction */
\r
491 cl_mutex_acquire( &p_adapter->mutex );
\r
492 cl_obj_lock( &p_adapter->obj );
\r
493 old_state = p_adapter->state;
\r
494 cl_obj_unlock( &p_adapter->obj );
\r
495 if( old_state == IB_PNP_PORT_REMOVE )
\r
497 cl_mutex_release( &p_adapter->mutex );
\r
498 IPOIB_TRACE_EXIT( IPOIB_DBG_PNP,
\r
499 ("Aborting - Adapter destroying.\n") );
\r
500 return IB_NOT_DONE;
\r
503 IPOIB_TRACE( IPOIB_DBG_INFO,
\r
504 ("p_pnp_rec->pnp_event = 0x%x\n",p_pnp_rec->pnp_event));
\r
506 switch( p_pnp_rec->pnp_event )
\r
508 case IB_PNP_PORT_ADD:
\r
509 CL_ASSERT( !p_pnp_rec->context );
\r
510 /* Only process our port GUID. */
\r
511 if( p_pnp_rec->guid != p_adapter->guids.port_guid )
\r
513 status = IB_NOT_DONE;
\r
517 /* Don't process if we're destroying. */
\r
518 if( p_adapter->obj.state == CL_DESTROYING )
\r
520 status = IB_NOT_DONE;
\r
524 CL_ASSERT( !p_adapter->p_port );
\r
525 /* Allocate all IB resources. */
\r
526 cl_obj_lock( &p_adapter->obj );
\r
527 p_adapter->state = IB_PNP_PORT_ADD;
\r
528 cl_obj_unlock( &p_adapter->obj );
\r
529 status = ipoib_create_port( p_adapter,
\r
530 (ib_pnp_port_rec_t*)p_pnp_rec, &p_adapter->p_port );
\r
531 if( status != IB_SUCCESS )
\r
533 cl_obj_lock( &p_adapter->obj );
\r
534 p_adapter->state = old_state;
\r
535 cl_obj_unlock( &p_adapter->obj );
\r
536 p_adapter->hung = TRUE;
\r
540 p_pnp_rec->context = p_adapter->p_port;
\r
543 case IB_PNP_PORT_REMOVE:
\r
544 /* Release all IB resources. */
\r
545 CL_ASSERT( p_pnp_rec->context );
\r
547 cl_obj_lock( &p_adapter->obj );
\r
548 p_adapter->state = IB_PNP_PORT_REMOVE;
\r
549 cl_obj_unlock( &p_adapter->obj );
\r
550 ipoib_port_destroy( p_adapter->p_port );
\r
551 p_adapter->p_port = NULL;
\r
552 p_pnp_rec->context = NULL;
\r
553 status = IB_SUCCESS;
\r
556 case IB_PNP_PORT_ACTIVE:
\r
557 /* Join multicast groups and put QP in RTS. */
\r
558 CL_ASSERT( p_pnp_rec->context );
\r
560 ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );
\r
562 status = IB_SUCCESS;
\r
565 case IB_PNP_PORT_INIT:
\r
566 case IB_PNP_PORT_ARMED:
\r
567 case IB_PNP_PORT_DOWN:
\r
568 /* Leave multicast groups. */
\r
569 CL_ASSERT( p_pnp_rec->context );
\r
571 cl_obj_lock( &p_adapter->obj );
\r
572 old_state = p_adapter->state;
\r
573 p_adapter->state = IB_PNP_PORT_DOWN;
\r
574 cl_obj_unlock( &p_adapter->obj );
\r
575 status = IB_SUCCESS;
\r
577 switch( old_state )
\r
579 case IB_PNP_PORT_ACTIVE:
\r
580 NdisMIndicateStatus( p_adapter->h_adapter,
\r
581 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );
\r
582 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
584 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link DOWN!\n") );
\r
586 ipoib_port_down( p_adapter->p_port );
\r
589 case IB_PNP_PORT_ADD:
\r
590 /* If we were initializing, we might have pended some OIDs. */
\r
591 ipoib_resume_oids( p_adapter );
\r
592 NdisMIndicateStatus( p_adapter->h_adapter,
\r
593 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );
\r
594 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
602 case IB_PNP_REG_COMPLETE:
\r
603 if( p_adapter->hung )
\r
605 p_adapter->hung = FALSE;
\r
606 NdisMResetComplete(
\r
607 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );
\r
609 status = IB_SUCCESS;
\r
613 IPOIB_TRACE( IPOIB_DBG_INFO,
\r
614 ("IPOIB: Received unhandled PnP event 0x%x\n",
\r
615 p_pnp_rec->pnp_event) );
\r
616 /* Fall through. */
\r
617 case IB_PNP_PKEY_CHANGE:
\r
618 case IB_PNP_SM_CHANGE:
\r
619 case IB_PNP_GID_CHANGE:
\r
620 case IB_PNP_LID_CHANGE:
\r
621 p_adapter->hung = TRUE;
\r
622 status = IB_SUCCESS;
\r
626 cl_mutex_release( &p_adapter->mutex );
\r
628 IPOIB_EXIT( IPOIB_DBG_PNP );
\r
633 /* Joins/leaves mcast groups based on currently programmed mcast MACs. */
\r
635 ipoib_refresh_mcast(
\r
636 IN ipoib_adapter_t* const p_adapter,
\r
637 IN mac_addr_t* const p_mac_array,
\r
638 IN const uint8_t num_macs )
\r
641 ipoib_port_t *p_port = NULL;
\r
643 IPOIB_ENTER( IPOIB_DBG_MCAST );
\r
644 cl_obj_lock( &p_adapter->obj );
\r
645 if( p_adapter->state == IB_PNP_PORT_ACTIVE )
\r
647 p_port = p_adapter->p_port;
\r
648 cl_obj_ref( &p_port->obj );
\r
650 cl_obj_unlock( &p_adapter->obj );
\r
654 /* Purge old entries. */
\r
655 for( i = 0; i < p_adapter->mcast_array_size; i++ )
\r
657 for( j = 0; j < num_macs; j++ )
\r
659 if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],
\r
660 sizeof(mac_addr_t) ) )
\r
665 if( j != num_macs )
\r
668 ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );
\r
671 /* Add new entries */
\r
672 for( i = 0; i < num_macs; i++ )
\r
674 for( j = 0; j < p_adapter->mcast_array_size; j++ )
\r
676 if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],
\r
677 sizeof(mac_addr_t) ) )
\r
683 if( j != p_adapter->mcast_array_size )
\r
686 ipoib_port_join_mcast( p_port, p_mac_array[i] );
\r
690 /* Copy the MAC array. */
\r
691 NdisMoveMemory( p_adapter->mcast_array, p_mac_array,
\r
692 num_macs * sizeof(mac_addr_t) );
\r
693 p_adapter->mcast_array_size = num_macs;
\r
696 cl_obj_deref( &p_port->obj );
\r
698 IPOIB_EXIT( IPOIB_DBG_MCAST );
\r
703 ipoib_reset_adapter(
\r
704 IN ipoib_adapter_t* const p_adapter )
\r
706 ib_api_status_t status;
\r
708 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
710 if( p_adapter->h_pnp )
\r
712 status = p_adapter->p_ifc->dereg_pnp(
\r
713 p_adapter->h_pnp, __ipoib_pnp_dereg );
\r
714 p_adapter->h_pnp = NULL;
\r
715 if( status == IB_SUCCESS )
\r
716 status = IB_NOT_DONE;
\r
720 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );
\r
721 if( status == IB_SUCCESS )
\r
722 p_adapter->hung = FALSE;
\r
725 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
734 ipoib_adapter_t* p_adapter;
\r
735 ib_api_status_t status;
\r
736 ib_pnp_event_t state;
\r
738 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
740 p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );
\r
742 /* Synchronize with destruction */
\r
743 cl_mutex_acquire( &p_adapter->mutex );
\r
745 cl_obj_lock( &p_adapter->obj );
\r
747 CL_ASSERT( !p_adapter->h_pnp );
\r
749 if( p_adapter->state != IB_PNP_PORT_REMOVE )
\r
750 p_adapter->state = IB_PNP_PORT_ADD;
\r
752 state = p_adapter->state;
\r
754 cl_obj_unlock( &p_adapter->obj );
\r
756 /* Destroy the current port instance if it still exists. */
\r
757 if( p_adapter->p_port )
\r
759 ipoib_port_destroy( p_adapter->p_port );
\r
760 p_adapter->p_port = NULL;
\r
762 /* Complete any pending OIDs. */
\r
763 ipoib_resume_oids( p_adapter );
\r
765 if( state != IB_PNP_PORT_REMOVE )
\r
767 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );
\r
768 if( status != IB_SUCCESS )
\r
770 p_adapter->hung = FALSE;
\r
771 IPOIB_TRACE( IPOIB_DBG_ERROR,
\r
772 ("__ipoib_pnp_reg returned %s\n",
\r
773 p_adapter->p_ifc->get_err_str( status )) );
\r
774 NdisMResetComplete(
\r
775 p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );
\r
780 p_adapter->hung = FALSE;
\r
781 NdisMResetComplete(
\r
782 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );
\r
783 status = IB_SUCCESS;
\r
786 /* Dereference the adapter since the previous registration is now gone. */
\r
787 cl_obj_deref( &p_adapter->obj );
\r
789 cl_mutex_release( &p_adapter->mutex );
\r
791 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
797 IN ipoib_adapter_t* const p_adapter,
\r
798 IN const uint8_t link_width )
\r
800 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
802 cl_obj_lock( &p_adapter->obj );
\r
803 /* Set the link speed based on the IB link speed (1x vs 4x, etc). */
\r
804 switch( link_width )
\r
806 case IB_LINK_WIDTH_ACTIVE_1X:
\r
807 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 2.5Gbps\n") );
\r
808 p_adapter->rate = ONE_X_IN_100BPS;
\r
811 case IB_LINK_WIDTH_ACTIVE_4X:
\r
812 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 10Gbps\n") );
\r
813 p_adapter->rate = FOUR_X_IN_100BPS;
\r
816 case IB_LINK_WIDTH_ACTIVE_12X:
\r
817 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 30Gbps\n") );
\r
818 p_adapter->rate = TWELVE_X_IN_100BPS;
\r
822 IPOIB_TRACE( IPOIB_DBG_INFO, ("Invalid rate.\n") );
\r
823 p_adapter->rate = 0;
\r
825 cl_obj_unlock( &p_adapter->obj );
\r
827 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
833 IN ipoib_adapter_t* const p_adapter )
\r
835 ib_pnp_event_t old_state;
\r
838 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
840 cl_obj_lock( &p_adapter->obj );
\r
841 old_state = p_adapter->state;
\r
843 /* Change the state to indicate that we are now connected and live. */
\r
844 if( old_state != IB_PNP_PORT_REMOVE )
\r
845 p_adapter->state = IB_PNP_PORT_ACTIVE;
\r
847 cl_obj_unlock( &p_adapter->obj );
\r
850 * If we had a pending OID request for OID_GEN_LINK_SPEED,
\r
853 switch( old_state )
\r
855 case IB_PNP_PORT_ADD:
\r
856 ipoib_reg_addrs( p_adapter );
\r
857 /* Fall through. */
\r
859 case IB_PNP_PORT_REMOVE:
\r
860 ipoib_resume_oids( p_adapter );
\r
864 /* Join all programmed multicast groups. */
\r
865 for( i = 0; i < p_adapter->mcast_array_size; i++ )
\r
867 ipoib_port_join_mcast( p_adapter->p_port, p_adapter->mcast_array[i] );
\r
870 /* Register all existing addresses. */
\r
871 ipoib_reg_addrs( p_adapter );
\r
873 /* Now that we're in the broadcast group, notify that we have a link. */
\r
874 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link UP!\n") );
\r
875 NdisMIndicateStatus( p_adapter->h_adapter, NDIS_STATUS_MEDIA_CONNECT,
\r
877 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
880 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
885 ipoib_get_recv_stat(
\r
886 IN ipoib_adapter_t* const p_adapter,
\r
887 IN const ip_stat_sel_t stat_sel,
\r
888 IN pending_oid_t* const p_oid_info )
\r
892 IPOIB_ENTER( IPOIB_DBG_INFO );
\r
894 CL_ASSERT( p_adapter );
\r
896 cl_spinlock_acquire( &p_adapter->recv_stat_lock );
\r
899 case IP_STAT_SUCCESS:
\r
900 stat = p_adapter->recv_stats.comp.success;
\r
903 case IP_STAT_ERROR:
\r
904 stat = p_adapter->recv_stats.comp.error;
\r
907 case IP_STAT_DROPPED:
\r
908 stat = p_adapter->recv_stats.comp.dropped;
\r
911 case IP_STAT_UCAST_BYTES:
\r
912 stat = p_adapter->recv_stats.ucast.bytes;
\r
915 case IP_STAT_UCAST_FRAMES:
\r
916 stat = p_adapter->recv_stats.ucast.frames;
\r
919 case IP_STAT_BCAST_BYTES:
\r
920 stat = p_adapter->recv_stats.bcast.bytes;
\r
923 case IP_STAT_BCAST_FRAMES:
\r
924 stat = p_adapter->recv_stats.bcast.frames;
\r
927 case IP_STAT_MCAST_BYTES:
\r
928 stat = p_adapter->recv_stats.mcast.bytes;
\r
931 case IP_STAT_MCAST_FRAMES:
\r
932 stat = p_adapter->recv_stats.mcast.frames;
\r
938 cl_spinlock_release( &p_adapter->recv_stat_lock );
\r
940 *p_oid_info->p_bytes_needed = sizeof(uint64_t);
\r
942 if( p_oid_info->buf_len >= sizeof(uint64_t) )
\r
944 *((uint64_t*)p_oid_info->p_buf) = stat;
\r
945 *p_oid_info->p_bytes_used = sizeof(uint64_t);
\r
947 else if( p_oid_info->buf_len >= sizeof(uint32_t) )
\r
949 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;
\r
950 *p_oid_info->p_bytes_used = sizeof(uint32_t);
\r
954 *p_oid_info->p_bytes_used = 0;
\r
955 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
956 return NDIS_STATUS_INVALID_LENGTH;
\r
959 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
960 return NDIS_STATUS_SUCCESS;
\r
965 ipoib_inc_recv_stat(
\r
966 IN ipoib_adapter_t* const p_adapter,
\r
967 IN const ip_stat_sel_t stat_sel,
\r
968 IN const size_t bytes OPTIONAL )
\r
970 IPOIB_ENTER( IPOIB_DBG_INFO );
\r
972 cl_spinlock_acquire( &p_adapter->recv_stat_lock );
\r
975 case IP_STAT_ERROR:
\r
976 p_adapter->recv_stats.comp.error++;
\r
979 case IP_STAT_DROPPED:
\r
980 p_adapter->recv_stats.comp.dropped++;
\r
983 case IP_STAT_UCAST_BYTES:
\r
984 case IP_STAT_UCAST_FRAMES:
\r
985 p_adapter->recv_stats.comp.success++;
\r
986 p_adapter->recv_stats.ucast.frames++;
\r
987 p_adapter->recv_stats.ucast.bytes += bytes;
\r
990 case IP_STAT_BCAST_BYTES:
\r
991 case IP_STAT_BCAST_FRAMES:
\r
992 p_adapter->recv_stats.comp.success++;
\r
993 p_adapter->recv_stats.bcast.frames++;
\r
994 p_adapter->recv_stats.bcast.bytes += bytes;
\r
997 case IP_STAT_MCAST_BYTES:
\r
998 case IP_STAT_MCAST_FRAMES:
\r
999 p_adapter->recv_stats.comp.success++;
\r
1000 p_adapter->recv_stats.mcast.frames++;
\r
1001 p_adapter->recv_stats.mcast.bytes += bytes;
\r
1007 cl_spinlock_release( &p_adapter->recv_stat_lock );
\r
1009 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
1013 ipoib_get_send_stat(
\r
1014 IN ipoib_adapter_t* const p_adapter,
\r
1015 IN const ip_stat_sel_t stat_sel,
\r
1016 IN pending_oid_t* const p_oid_info )
\r
1020 IPOIB_ENTER( IPOIB_DBG_INFO );
\r
1022 CL_ASSERT( p_adapter );
\r
1024 cl_spinlock_acquire( &p_adapter->send_stat_lock );
\r
1025 switch( stat_sel )
\r
1027 case IP_STAT_SUCCESS:
\r
1028 stat = p_adapter->send_stats.comp.success;
\r
1031 case IP_STAT_ERROR:
\r
1032 stat = p_adapter->send_stats.comp.error;
\r
1035 case IP_STAT_DROPPED:
\r
1036 stat = p_adapter->send_stats.comp.dropped;
\r
1039 case IP_STAT_UCAST_BYTES:
\r
1040 stat = p_adapter->send_stats.ucast.bytes;
\r
1043 case IP_STAT_UCAST_FRAMES:
\r
1044 stat = p_adapter->send_stats.ucast.frames;
\r
1047 case IP_STAT_BCAST_BYTES:
\r
1048 stat = p_adapter->send_stats.bcast.bytes;
\r
1051 case IP_STAT_BCAST_FRAMES:
\r
1052 stat = p_adapter->send_stats.bcast.frames;
\r
1055 case IP_STAT_MCAST_BYTES:
\r
1056 stat = p_adapter->send_stats.mcast.bytes;
\r
1059 case IP_STAT_MCAST_FRAMES:
\r
1060 stat = p_adapter->send_stats.mcast.frames;
\r
1066 cl_spinlock_release( &p_adapter->send_stat_lock );
\r
1068 *p_oid_info->p_bytes_needed = sizeof(uint64_t);
\r
1070 if( p_oid_info->buf_len >= sizeof(uint64_t) )
\r
1072 *((uint64_t*)p_oid_info->p_buf) = stat;
\r
1073 *p_oid_info->p_bytes_used = sizeof(uint64_t);
\r
1075 else if( p_oid_info->buf_len >= sizeof(uint32_t) )
\r
1077 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;
\r
1078 *p_oid_info->p_bytes_used = sizeof(uint32_t);
\r
1082 *p_oid_info->p_bytes_used = 0;
\r
1083 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
1084 return NDIS_STATUS_INVALID_LENGTH;
\r
1087 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
1088 return NDIS_STATUS_SUCCESS;
\r
1093 ipoib_inc_send_stat(
\r
1094 IN ipoib_adapter_t* const p_adapter,
\r
1095 IN const ip_stat_sel_t stat_sel,
\r
1096 IN const size_t bytes OPTIONAL )
\r
1098 IPOIB_ENTER( IPOIB_DBG_INFO );
\r
1100 cl_spinlock_acquire( &p_adapter->send_stat_lock );
\r
1101 switch( stat_sel )
\r
1103 case IP_STAT_ERROR:
\r
1104 p_adapter->send_stats.comp.error++;
\r
1107 case IP_STAT_DROPPED:
\r
1108 p_adapter->send_stats.comp.dropped++;
\r
1111 case IP_STAT_UCAST_BYTES:
\r
1112 case IP_STAT_UCAST_FRAMES:
\r
1113 p_adapter->send_stats.comp.success++;
\r
1114 p_adapter->send_stats.ucast.frames++;
\r
1115 p_adapter->send_stats.ucast.bytes += bytes;
\r
1118 case IP_STAT_BCAST_BYTES:
\r
1119 case IP_STAT_BCAST_FRAMES:
\r
1120 p_adapter->send_stats.comp.success++;
\r
1121 p_adapter->send_stats.bcast.frames++;
\r
1122 p_adapter->send_stats.bcast.bytes += bytes;
\r
1125 case IP_STAT_MCAST_BYTES:
\r
1126 case IP_STAT_MCAST_FRAMES:
\r
1127 p_adapter->send_stats.comp.success++;
\r
1128 p_adapter->send_stats.mcast.frames++;
\r
1129 p_adapter->send_stats.mcast.bytes += bytes;
\r
1135 cl_spinlock_release( &p_adapter->send_stat_lock );
\r
1137 IPOIB_EXIT( IPOIB_DBG_INFO );
\r