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 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
131 p_adapter = cl_zalloc( sizeof(ipoib_adapter_t) );
\r
134 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
135 ("Failed to allocate ipoib_adapter_t (%d bytes)",
\r
136 sizeof(ipoib_adapter_t)) );
\r
137 return IB_INSUFFICIENT_MEMORY;
\r
140 adapter_construct( p_adapter );
\r
142 p_adapter->h_adapter = h_adapter;
\r
144 p_adapter->p_ifc = cl_zalloc( sizeof(ib_al_ifc_t) );
\r
145 if( !p_adapter->p_ifc )
\r
147 __adapter_free( &p_adapter->obj );
\r
148 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
149 ("ipoib_create_adapter failed to alloc ipoib_ifc_t % bytes\n",
\r
150 sizeof(ib_al_ifc_t)) );
\r
151 return IB_INSUFFICIENT_MEMORY;
\r
154 /* Get the CA and port GUID from the bus driver. */
\r
155 status = ipoib_get_adapter_guids( h_adapter, p_adapter );
\r
156 if( status != NDIS_STATUS_SUCCESS )
\r
158 __adapter_free( &p_adapter->obj );
\r
159 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
160 ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );
\r
164 IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,
\r
165 ("Port %016I64x (CA %016I64x port %d) initializing\n",
\r
166 p_adapter->guids.port_guid, p_adapter->guids.ca_guid,
\r
167 p_adapter->guids.port_num) );
\r
169 /* Read configuration parameters. */
\r
170 status = ipoib_get_adapter_params( wrapper_config_context,
\r
171 &p_adapter->params );
\r
172 if( status != NDIS_STATUS_SUCCESS )
\r
174 __adapter_free( &p_adapter->obj );
\r
175 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
176 ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );
\r
180 cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC,
\r
181 __adapter_destroying, NULL, __adapter_free );
\r
182 if( cl_status != CL_SUCCESS )
\r
184 __adapter_free( &p_adapter->obj );
\r
185 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
186 ("cl_obj_init returned %s\n", cl_status_text[cl_status]) );
\r
190 status = adapter_init( p_adapter );
\r
191 if( status != IB_SUCCESS )
\r
193 cl_obj_destroy( &p_adapter->obj );
\r
194 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
195 ("adapter_init returned %s.\n",
\r
196 p_adapter->p_ifc->get_err_str( status )) );
\r
200 *pp_adapter = p_adapter;
\r
202 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
208 ipoib_start_adapter(
\r
209 IN ipoib_adapter_t* const p_adapter )
\r
211 ib_api_status_t status;
\r
213 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
215 status = __ipoib_pnp_reg( p_adapter,
\r
216 IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE );
\r
218 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
224 ipoib_destroy_adapter(
\r
225 IN ipoib_adapter_t* const p_adapter )
\r
227 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
229 CL_ASSERT( p_adapter );
\r
232 * Flag the adapter as being removed. We use the IB_PNP_PORT_REMOVE state
\r
233 * for this purpose. Note that we protect this state change with both the
\r
234 * mutex and the lock. The mutex provides synchronization as a whole
\r
235 * between destruction and AL callbacks (PnP, Query, Destruction).
\r
236 * The lock provides protection
\r
238 KeWaitForMutexObject(
\r
239 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );
\r
240 cl_obj_lock( &p_adapter->obj );
\r
241 p_adapter->state = IB_PNP_PORT_REMOVE;
\r
244 * Clear the pointer to the port object since the object destruction
\r
245 * will cascade to child objects. This prevents potential duplicate
\r
246 * destruction (or worse, stale pointer usage).
\r
248 p_adapter->p_port = NULL;
\r
250 cl_obj_unlock( &p_adapter->obj );
\r
252 KeReleaseMutex( &p_adapter->mutex, FALSE );
\r
254 cl_obj_destroy( &p_adapter->obj );
\r
256 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
262 IN ipoib_adapter_t* const p_adapter )
\r
264 cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );
\r
265 cl_spinlock_construct( &p_adapter->send_stat_lock );
\r
266 cl_spinlock_construct( &p_adapter->recv_stat_lock );
\r
267 cl_qpool_construct( &p_adapter->item_pool );
\r
268 KeInitializeMutex( &p_adapter->mutex, 0 );
\r
269 cl_vector_construct( &p_adapter->ip_vector );
\r
271 cl_perf_construct( &p_adapter->perf );
\r
273 p_adapter->state = IB_PNP_PORT_ADD;
\r
274 p_adapter->rate = FOUR_X_IN_100BPS;
\r
278 static ib_api_status_t
\r
280 IN ipoib_adapter_t* const p_adapter )
\r
282 cl_status_t cl_status;
\r
283 ib_api_status_t status;
\r
285 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
287 cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );
\r
288 if( cl_status != CL_SUCCESS )
\r
290 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
291 ("cl_perf_init returned %s\n", cl_status_text[cl_status]) );
\r
295 cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );
\r
296 if( cl_status != CL_SUCCESS )
\r
298 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
299 ("cl_spinlock_init returned %s\n", cl_status_text[cl_status]) );
\r
303 cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );
\r
304 if( cl_status != CL_SUCCESS )
\r
306 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
307 ("cl_spinlock_init returned %s\n", cl_status_text[cl_status]) );
\r
311 cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,
\r
312 ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );
\r
313 if( cl_status != CL_SUCCESS )
\r
315 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
316 ("cl_qpool_init returned %s\n", cl_status_text[cl_status]) );
\r
321 /* We manually manage the size and capacity of the vector. */
\r
322 cl_status = cl_vector_init( &p_adapter->ip_vector, 0,
\r
323 0, sizeof(net_address_item_t), NULL, NULL, p_adapter );
\r
324 if( cl_status != CL_SUCCESS )
\r
326 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
327 ("cl_vector_init for ip_vector returned %s\n",
\r
328 CL_STATUS_MSG(cl_status)) );
\r
332 /* Validate the port GUID and generate the MAC address. */
\r
334 ipoib_mac_from_guid( p_adapter->guids.port_guid, &p_adapter->mac );
\r
335 if( status != IB_SUCCESS )
\r
337 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
338 ("ipoib_mac_from_guid returned %s\n",
\r
339 p_adapter->p_ifc->get_err_str( status )) );
\r
344 status = p_adapter->p_ifc->open_al( &p_adapter->h_al );
\r
345 if( status != IB_SUCCESS )
\r
347 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
348 ("ib_open_al returned %s\n",
\r
349 p_adapter->p_ifc->get_err_str( status )) );
\r
353 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
358 static ib_api_status_t
\r
360 IN ipoib_adapter_t* const p_adapter,
\r
361 IN ib_pnp_class_t flags )
\r
363 ib_api_status_t status;
\r
364 ib_pnp_req_t pnp_req;
\r
366 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
368 CL_ASSERT( !p_adapter->h_pnp );
\r
369 CL_ASSERT( !p_adapter->registering );
\r
371 p_adapter->registering = TRUE;
\r
373 /* Register for PNP events. */
\r
374 cl_memclr( &pnp_req, sizeof(pnp_req) );
\r
375 pnp_req.pnp_class = IB_PNP_PORT | flags;
\r
377 * Context is the cl_obj of the adapter to allow passing cl_obj_deref
\r
380 pnp_req.pnp_context = &p_adapter->obj;
\r
381 pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;
\r
382 status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );
\r
383 if( status != IB_SUCCESS )
\r
385 p_adapter->registering = FALSE;
\r
386 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
387 ("ib_reg_pnp returned %s\n",
\r
388 p_adapter->p_ifc->get_err_str( status )) );
\r
392 * Reference the adapter on behalf of the PNP registration.
\r
393 * This allows the destruction to block until the PNP deregistration
\r
396 cl_obj_ref( &p_adapter->obj );
\r
398 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
404 __adapter_destroying(
\r
405 IN cl_obj_t* const p_obj )
\r
407 ipoib_adapter_t *p_adapter;
\r
408 KLOCK_QUEUE_HANDLE hdl;
\r
410 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
412 p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );
\r
415 * The adapter's object will be dereferenced when the deregistration
\r
416 * completes. No need to lock here since all PnP related API calls
\r
417 * are driven by NDIS (via the Init/Reset/Destroy paths).
\r
419 if( p_adapter->h_pnp )
\r
421 p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, cl_obj_deref );
\r
422 p_adapter->h_pnp = NULL;
\r
425 if( p_adapter->packet_filter )
\r
427 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
\r
428 cl_obj_lock( &p_adapter->obj );
\r
430 ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );
\r
431 cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry );
\r
433 p_adapter->packet_filter = 0;
\r
435 cl_obj_unlock( &p_adapter->obj );
\r
436 KeReleaseInStackQueuedSpinLock( &hdl );
\r
439 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
445 IN cl_obj_t* const p_obj )
\r
447 ipoib_adapter_t *p_adapter;
\r
449 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
451 p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );
\r
453 if( p_adapter->p_ifc )
\r
455 if( p_adapter->h_al )
\r
456 p_adapter->p_ifc->close_al( p_adapter->h_al );
\r
458 cl_free( p_adapter->p_ifc );
\r
461 cl_vector_destroy( &p_adapter->ip_vector );
\r
462 cl_qpool_destroy( &p_adapter->item_pool );
\r
463 cl_spinlock_destroy( &p_adapter->recv_stat_lock );
\r
464 cl_spinlock_destroy( &p_adapter->send_stat_lock );
\r
465 cl_obj_deinit( p_obj );
\r
467 cl_perf_destroy( &p_adapter->perf, TRUE );
\r
469 cl_free( p_adapter );
\r
471 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
475 static ib_api_status_t
\r
477 IN ib_pnp_rec_t *p_pnp_rec )
\r
479 ib_api_status_t status;
\r
480 ipoib_adapter_t *p_adapter;
\r
481 ipoib_port_t *p_port;
\r
482 ib_pnp_event_t old_state;
\r
484 IPOIB_ENTER( IPOIB_DBG_PNP );
\r
486 CL_ASSERT( p_pnp_rec );
\r
489 PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );
\r
491 CL_ASSERT( p_adapter );
\r
493 /* Synchronize with destruction */
\r
494 KeWaitForMutexObject(
\r
495 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );
\r
496 cl_obj_lock( &p_adapter->obj );
\r
497 old_state = p_adapter->state;
\r
498 cl_obj_unlock( &p_adapter->obj );
\r
499 if( old_state == IB_PNP_PORT_REMOVE )
\r
501 KeReleaseMutex( &p_adapter->mutex, FALSE );
\r
502 IPOIB_TRACE_EXIT( IPOIB_DBG_PNP,
\r
503 ("Aborting - Adapter destroying.\n") );
\r
504 return IB_NOT_DONE;
\r
507 IPOIB_TRACE( IPOIB_DBG_INFO,
\r
508 ("p_pnp_rec->pnp_event = 0x%x\n",p_pnp_rec->pnp_event));
\r
510 switch( p_pnp_rec->pnp_event )
\r
512 case IB_PNP_PORT_ADD:
\r
513 CL_ASSERT( !p_pnp_rec->context );
\r
514 /* Only process our port GUID. */
\r
515 if( p_pnp_rec->guid != p_adapter->guids.port_guid )
\r
517 status = IB_NOT_DONE;
\r
521 /* Don't process if we're destroying. */
\r
522 if( p_adapter->obj.state == CL_DESTROYING )
\r
524 status = IB_NOT_DONE;
\r
528 CL_ASSERT( !p_adapter->p_port );
\r
529 /* Allocate all IB resources. */
\r
530 cl_obj_lock( &p_adapter->obj );
\r
531 p_adapter->state = IB_PNP_PORT_ADD;
\r
532 cl_obj_unlock( &p_adapter->obj );
\r
533 status = ipoib_create_port( p_adapter,
\r
534 (ib_pnp_port_rec_t*)p_pnp_rec, &p_port );
\r
535 cl_obj_lock( &p_adapter->obj );
\r
536 if( status != IB_SUCCESS )
\r
538 p_adapter->state = old_state;
\r
539 cl_obj_unlock( &p_adapter->obj );
\r
540 p_adapter->hung = TRUE;
\r
544 p_pnp_rec->context = p_port;
\r
546 p_adapter->p_port = p_port;
\r
547 cl_obj_unlock( &p_adapter->obj );
\r
550 case IB_PNP_PORT_REMOVE:
\r
551 /* Release all IB resources. */
\r
552 CL_ASSERT( p_pnp_rec->context );
\r
554 cl_obj_lock( &p_adapter->obj );
\r
555 p_adapter->state = IB_PNP_PORT_REMOVE;
\r
556 p_port = p_adapter->p_port;
\r
557 p_adapter->p_port = NULL;
\r
558 cl_obj_unlock( &p_adapter->obj );
\r
559 ipoib_port_destroy( p_port );
\r
560 p_pnp_rec->context = NULL;
\r
561 status = IB_SUCCESS;
\r
564 case IB_PNP_PORT_ACTIVE:
\r
565 /* Join multicast groups and put QP in RTS. */
\r
566 CL_ASSERT( p_pnp_rec->context );
\r
568 cl_obj_lock( &p_adapter->obj );
\r
569 p_adapter->state = IB_PNP_PORT_INIT;
\r
570 cl_obj_unlock( &p_adapter->obj );
\r
571 ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );
\r
573 status = IB_SUCCESS;
\r
576 case IB_PNP_PORT_ARMED:
\r
577 status = IB_SUCCESS;
\r
580 case IB_PNP_PORT_INIT:
\r
582 * Init could happen if the SM brings the port down
\r
583 * without changing the physical link.
\r
585 case IB_PNP_PORT_DOWN:
\r
586 CL_ASSERT( p_pnp_rec->context );
\r
588 cl_obj_lock( &p_adapter->obj );
\r
589 old_state = p_adapter->state;
\r
590 p_adapter->state = IB_PNP_PORT_DOWN;
\r
591 cl_obj_unlock( &p_adapter->obj );
\r
592 status = IB_SUCCESS;
\r
594 if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN )
\r
596 NdisMIndicateStatus( p_adapter->h_adapter,
\r
597 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );
\r
598 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
600 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link DOWN!\n") );
\r
602 ipoib_port_down( p_adapter->p_port );
\r
606 case IB_PNP_REG_COMPLETE:
\r
607 if( p_adapter->registering )
\r
609 p_adapter->registering = FALSE;
\r
610 cl_obj_lock( &p_adapter->obj );
\r
611 old_state = p_adapter->state;
\r
612 cl_obj_unlock( &p_adapter->obj );
\r
614 if( old_state == IB_PNP_PORT_DOWN )
\r
616 /* If we were initializing, we might have pended some OIDs. */
\r
617 ipoib_resume_oids( p_adapter );
\r
618 NdisMIndicateStatus( p_adapter->h_adapter,
\r
619 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );
\r
620 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
624 if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT )
\r
626 p_adapter->reset = FALSE;
\r
627 NdisMResetComplete(
\r
628 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );
\r
630 status = IB_SUCCESS;
\r
634 IPOIB_TRACE( IPOIB_DBG_INFO,
\r
635 ("IPOIB: Received unhandled PnP event 0x%x\n",
\r
636 p_pnp_rec->pnp_event) );
\r
637 /* Fall through. */
\r
638 case IB_PNP_PKEY_CHANGE:
\r
639 case IB_PNP_SM_CHANGE:
\r
640 case IB_PNP_GID_CHANGE:
\r
641 case IB_PNP_LID_CHANGE:
\r
642 cl_obj_lock( &p_adapter->obj );
\r
643 old_state = p_adapter->state;
\r
644 switch( old_state )
\r
646 case IB_PNP_PORT_DOWN:
\r
647 p_adapter->state = IB_PNP_PORT_INIT;
\r
651 p_adapter->state = IB_PNP_PORT_DOWN;
\r
653 cl_obj_unlock( &p_adapter->obj );
\r
655 status = IB_SUCCESS;
\r
656 if( p_adapter->registering )
\r
659 switch( old_state )
\r
661 case IB_PNP_PORT_ACTIVE:
\r
662 NdisMIndicateStatus( p_adapter->h_adapter,
\r
663 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );
\r
664 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
666 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link DOWN!\n") );
\r
668 ipoib_port_down( p_adapter->p_port );
\r
669 /* Fall through. */
\r
671 case IB_PNP_PORT_DOWN:
\r
672 ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );
\r
677 KeReleaseMutex( &p_adapter->mutex, FALSE );
\r
679 IPOIB_EXIT( IPOIB_DBG_PNP );
\r
684 /* Joins/leaves mcast groups based on currently programmed mcast MACs. */
\r
686 ipoib_refresh_mcast(
\r
687 IN ipoib_adapter_t* const p_adapter,
\r
688 IN mac_addr_t* const p_mac_array,
\r
689 IN const uint8_t num_macs )
\r
692 ipoib_port_t *p_port = NULL;
\r
694 IPOIB_ENTER( IPOIB_DBG_MCAST );
\r
695 cl_obj_lock( &p_adapter->obj );
\r
696 if( p_adapter->state == IB_PNP_PORT_ACTIVE )
\r
698 p_port = p_adapter->p_port;
\r
699 cl_obj_ref( &p_port->obj );
\r
701 cl_obj_unlock( &p_adapter->obj );
\r
705 /* Purge old entries. */
\r
706 for( i = 0; i < p_adapter->mcast_array_size; i++ )
\r
708 for( j = 0; j < num_macs; j++ )
\r
710 if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],
\r
711 sizeof(mac_addr_t) ) )
\r
716 if( j != num_macs )
\r
719 ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );
\r
722 /* Add new entries */
\r
723 for( i = 0; i < num_macs; i++ )
\r
725 for( j = 0; j < p_adapter->mcast_array_size; j++ )
\r
727 if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],
\r
728 sizeof(mac_addr_t) ) )
\r
734 if( j != p_adapter->mcast_array_size )
\r
737 ipoib_port_join_mcast( p_port, p_mac_array[i] );
\r
741 /* Copy the MAC array. */
\r
742 NdisMoveMemory( p_adapter->mcast_array, p_mac_array,
\r
743 num_macs * sizeof(mac_addr_t) );
\r
744 p_adapter->mcast_array_size = num_macs;
\r
747 cl_obj_deref( &p_port->obj );
\r
749 IPOIB_EXIT( IPOIB_DBG_MCAST );
\r
754 ipoib_reset_adapter(
\r
755 IN ipoib_adapter_t* const p_adapter )
\r
757 ib_api_status_t status;
\r
758 ib_pnp_handle_t h_pnp;
\r
760 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
762 if( p_adapter->reset )
\r
763 return IB_INVALID_STATE;
\r
765 p_adapter->hung = FALSE;
\r
766 p_adapter->reset = TRUE;
\r
768 if( p_adapter->h_pnp )
\r
770 h_pnp = p_adapter->h_pnp;
\r
771 p_adapter->h_pnp = NULL;
\r
772 status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg );
\r
773 if( status == IB_SUCCESS )
\r
774 status = IB_NOT_DONE;
\r
778 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );
\r
779 if( status == IB_SUCCESS )
\r
780 p_adapter->hung = FALSE;
\r
783 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
792 ipoib_adapter_t* p_adapter;
\r
793 ipoib_port_t* p_port;
\r
794 ib_api_status_t status;
\r
795 ib_pnp_event_t state;
\r
797 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
799 p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );
\r
801 /* Synchronize with destruction */
\r
802 KeWaitForMutexObject(
\r
803 &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );
\r
805 cl_obj_lock( &p_adapter->obj );
\r
807 CL_ASSERT( !p_adapter->h_pnp );
\r
809 if( p_adapter->state != IB_PNP_PORT_REMOVE )
\r
810 p_adapter->state = IB_PNP_PORT_ADD;
\r
812 state = p_adapter->state;
\r
814 /* Destroy the current port instance if it still exists. */
\r
815 p_port = p_adapter->p_port;
\r
816 p_adapter->p_port = NULL;
\r
817 cl_obj_unlock( &p_adapter->obj );
\r
820 ipoib_port_destroy( p_port );
\r
822 if( state != IB_PNP_PORT_REMOVE )
\r
824 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );
\r
825 if( status != IB_SUCCESS )
\r
827 p_adapter->reset = FALSE;
\r
828 IPOIB_TRACE( IPOIB_DBG_ERROR,
\r
829 ("__ipoib_pnp_reg returned %s\n",
\r
830 p_adapter->p_ifc->get_err_str( status )) );
\r
831 NdisMResetComplete(
\r
832 p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );
\r
837 p_adapter->reset = FALSE;
\r
838 NdisMResetComplete(
\r
839 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );
\r
840 status = IB_SUCCESS;
\r
843 /* Dereference the adapter since the previous registration is now gone. */
\r
844 cl_obj_deref( &p_adapter->obj );
\r
846 KeReleaseMutex( &p_adapter->mutex, FALSE );
\r
848 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
854 IN ipoib_adapter_t* const p_adapter,
\r
855 IN const uint8_t link_width,
\r
856 IN const uint8_t link_speed )
\r
858 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
860 cl_obj_lock( &p_adapter->obj );
\r
861 /* Set the link speed based on the IB link speed (1x vs 4x, etc). */
\r
862 switch( link_speed )
\r
864 case IB_LINK_SPEED_ACTIVE_2_5:
\r
865 IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,
\r
866 ("Link speed is 2.5Gs\n") );
\r
867 p_adapter->rate = IB_LINK_SPEED_ACTIVE_2_5;
\r
870 case IB_LINK_SPEED_ACTIVE_5:
\r
871 IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,
\r
872 ("Link speed is 5G\n") );
\r
873 p_adapter->rate = IB_LINK_SPEED_ACTIVE_5;
\r
876 case IB_LINK_SPEED_ACTIVE_10:
\r
877 IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,
\r
878 ("Link speed is 10G\n") );
\r
879 p_adapter->rate = IB_LINK_SPEED_ACTIVE_10;
\r
883 IPOIB_TRACE( IPOIB_DBG_ERROR,
\r
884 ("Invalid link speed %d.\n", link_speed) );
\r
885 p_adapter->rate = 0;
\r
888 switch( link_width )
\r
890 case IB_LINK_WIDTH_ACTIVE_1X:
\r
891 IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,
\r
892 ("Link width is 1X\n") );
\r
893 p_adapter->rate *= ONE_X_IN_100BPS;
\r
896 case IB_LINK_WIDTH_ACTIVE_4X:
\r
897 IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,
\r
898 ("Link width is 4X\n") );
\r
899 p_adapter->rate *= FOUR_X_IN_100BPS;
\r
902 case IB_LINK_WIDTH_ACTIVE_12X:
\r
903 IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,
\r
904 ("Link width is 12X\n") );
\r
905 p_adapter->rate *= TWELVE_X_IN_100BPS;
\r
909 IPOIB_TRACE( IPOIB_DBG_ERROR,
\r
910 ("Invalid link rate (%d).\n", link_width) );
\r
911 p_adapter->rate = 0;
\r
913 cl_obj_unlock( &p_adapter->obj );
\r
914 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
920 IN ipoib_adapter_t* const p_adapter )
\r
922 ib_pnp_event_t old_state;
\r
925 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
927 cl_obj_lock( &p_adapter->obj );
\r
928 old_state = p_adapter->state;
\r
930 /* Change the state to indicate that we are now connected and live. */
\r
931 if( old_state != IB_PNP_PORT_REMOVE )
\r
932 p_adapter->state = IB_PNP_PORT_ACTIVE;
\r
934 cl_obj_unlock( &p_adapter->obj );
\r
937 * If we had a pending OID request for OID_GEN_LINK_SPEED,
\r
940 switch( old_state )
\r
942 case IB_PNP_PORT_ADD:
\r
943 ipoib_reg_addrs( p_adapter );
\r
944 /* Fall through. */
\r
946 case IB_PNP_PORT_REMOVE:
\r
947 ipoib_resume_oids( p_adapter );
\r
951 /* Join all programmed multicast groups. */
\r
952 for( i = 0; i < p_adapter->mcast_array_size; i++ )
\r
954 ipoib_port_join_mcast(
\r
955 p_adapter->p_port, p_adapter->mcast_array[i] );
\r
958 /* Register all existing addresses. */
\r
959 ipoib_reg_addrs( p_adapter );
\r
961 ipoib_resume_oids( p_adapter );
\r
964 * Now that we're in the broadcast group, notify that
\r
967 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link UP!\n") );
\r
968 NdisWriteErrorLogEntry( p_adapter->h_adapter,
\r
969 EVENT_IPOIB_PORT_UP + (p_adapter->rate/ONE_X_IN_100BPS),
\r
970 1, p_adapter->rate );
\r
972 if( !p_adapter->reset )
\r
974 NdisMIndicateStatus( p_adapter->h_adapter, NDIS_STATUS_MEDIA_CONNECT,
\r
976 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
980 if( p_adapter->reset )
\r
982 p_adapter->reset = FALSE;
\r
983 NdisMResetComplete(
\r
984 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );
\r
987 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
992 ipoib_get_recv_stat(
\r
993 IN ipoib_adapter_t* const p_adapter,
\r
994 IN const ip_stat_sel_t stat_sel,
\r
995 IN pending_oid_t* const p_oid_info )
\r
999 IPOIB_ENTER( IPOIB_DBG_STAT );
\r
1001 CL_ASSERT( p_adapter );
\r
1003 cl_spinlock_acquire( &p_adapter->recv_stat_lock );
\r
1004 switch( stat_sel )
\r
1006 case IP_STAT_SUCCESS:
\r
1007 stat = p_adapter->recv_stats.comp.success;
\r
1010 case IP_STAT_ERROR:
\r
1011 stat = p_adapter->recv_stats.comp.error;
\r
1014 case IP_STAT_DROPPED:
\r
1015 stat = p_adapter->recv_stats.comp.dropped;
\r
1018 case IP_STAT_UCAST_BYTES:
\r
1019 stat = p_adapter->recv_stats.ucast.bytes;
\r
1022 case IP_STAT_UCAST_FRAMES:
\r
1023 stat = p_adapter->recv_stats.ucast.frames;
\r
1026 case IP_STAT_BCAST_BYTES:
\r
1027 stat = p_adapter->recv_stats.bcast.bytes;
\r
1030 case IP_STAT_BCAST_FRAMES:
\r
1031 stat = p_adapter->recv_stats.bcast.frames;
\r
1034 case IP_STAT_MCAST_BYTES:
\r
1035 stat = p_adapter->recv_stats.mcast.bytes;
\r
1038 case IP_STAT_MCAST_FRAMES:
\r
1039 stat = p_adapter->recv_stats.mcast.frames;
\r
1045 cl_spinlock_release( &p_adapter->recv_stat_lock );
\r
1047 *p_oid_info->p_bytes_needed = sizeof(uint64_t);
\r
1049 if( p_oid_info->buf_len >= sizeof(uint64_t) )
\r
1051 *((uint64_t*)p_oid_info->p_buf) = stat;
\r
1052 *p_oid_info->p_bytes_used = sizeof(uint64_t);
\r
1054 else if( p_oid_info->buf_len >= sizeof(uint32_t) )
\r
1056 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;
\r
1057 *p_oid_info->p_bytes_used = sizeof(uint32_t);
\r
1061 *p_oid_info->p_bytes_used = 0;
\r
1062 IPOIB_EXIT( IPOIB_DBG_STAT );
\r
1063 return NDIS_STATUS_INVALID_LENGTH;
\r
1066 IPOIB_EXIT( IPOIB_DBG_STAT );
\r
1067 return NDIS_STATUS_SUCCESS;
\r
1072 ipoib_inc_recv_stat(
\r
1073 IN ipoib_adapter_t* const p_adapter,
\r
1074 IN const ip_stat_sel_t stat_sel,
\r
1075 IN const size_t bytes OPTIONAL )
\r
1077 IPOIB_ENTER( IPOIB_DBG_STAT );
\r
1079 cl_spinlock_acquire( &p_adapter->recv_stat_lock );
\r
1080 switch( stat_sel )
\r
1082 case IP_STAT_ERROR:
\r
1083 p_adapter->recv_stats.comp.error++;
\r
1086 case IP_STAT_DROPPED:
\r
1087 p_adapter->recv_stats.comp.dropped++;
\r
1090 case IP_STAT_UCAST_BYTES:
\r
1091 case IP_STAT_UCAST_FRAMES:
\r
1092 p_adapter->recv_stats.comp.success++;
\r
1093 p_adapter->recv_stats.ucast.frames++;
\r
1094 p_adapter->recv_stats.ucast.bytes += bytes;
\r
1097 case IP_STAT_BCAST_BYTES:
\r
1098 case IP_STAT_BCAST_FRAMES:
\r
1099 p_adapter->recv_stats.comp.success++;
\r
1100 p_adapter->recv_stats.bcast.frames++;
\r
1101 p_adapter->recv_stats.bcast.bytes += bytes;
\r
1104 case IP_STAT_MCAST_BYTES:
\r
1105 case IP_STAT_MCAST_FRAMES:
\r
1106 p_adapter->recv_stats.comp.success++;
\r
1107 p_adapter->recv_stats.mcast.frames++;
\r
1108 p_adapter->recv_stats.mcast.bytes += bytes;
\r
1114 cl_spinlock_release( &p_adapter->recv_stat_lock );
\r
1116 IPOIB_EXIT( IPOIB_DBG_STAT );
\r
1120 ipoib_get_send_stat(
\r
1121 IN ipoib_adapter_t* const p_adapter,
\r
1122 IN const ip_stat_sel_t stat_sel,
\r
1123 IN pending_oid_t* const p_oid_info )
\r
1127 IPOIB_ENTER( IPOIB_DBG_STAT );
\r
1129 CL_ASSERT( p_adapter );
\r
1131 cl_spinlock_acquire( &p_adapter->send_stat_lock );
\r
1132 switch( stat_sel )
\r
1134 case IP_STAT_SUCCESS:
\r
1135 stat = p_adapter->send_stats.comp.success;
\r
1138 case IP_STAT_ERROR:
\r
1139 stat = p_adapter->send_stats.comp.error;
\r
1142 case IP_STAT_DROPPED:
\r
1143 stat = p_adapter->send_stats.comp.dropped;
\r
1146 case IP_STAT_UCAST_BYTES:
\r
1147 stat = p_adapter->send_stats.ucast.bytes;
\r
1150 case IP_STAT_UCAST_FRAMES:
\r
1151 stat = p_adapter->send_stats.ucast.frames;
\r
1154 case IP_STAT_BCAST_BYTES:
\r
1155 stat = p_adapter->send_stats.bcast.bytes;
\r
1158 case IP_STAT_BCAST_FRAMES:
\r
1159 stat = p_adapter->send_stats.bcast.frames;
\r
1162 case IP_STAT_MCAST_BYTES:
\r
1163 stat = p_adapter->send_stats.mcast.bytes;
\r
1166 case IP_STAT_MCAST_FRAMES:
\r
1167 stat = p_adapter->send_stats.mcast.frames;
\r
1173 cl_spinlock_release( &p_adapter->send_stat_lock );
\r
1175 *p_oid_info->p_bytes_needed = sizeof(uint64_t);
\r
1177 if( p_oid_info->buf_len >= sizeof(uint64_t) )
\r
1179 *((uint64_t*)p_oid_info->p_buf) = stat;
\r
1180 *p_oid_info->p_bytes_used = sizeof(uint64_t);
\r
1182 else if( p_oid_info->buf_len >= sizeof(uint32_t) )
\r
1184 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;
\r
1185 *p_oid_info->p_bytes_used = sizeof(uint32_t);
\r
1189 *p_oid_info->p_bytes_used = 0;
\r
1190 IPOIB_EXIT( IPOIB_DBG_STAT );
\r
1191 return NDIS_STATUS_INVALID_LENGTH;
\r
1194 IPOIB_EXIT( IPOIB_DBG_STAT );
\r
1195 return NDIS_STATUS_SUCCESS;
\r
1200 ipoib_inc_send_stat(
\r
1201 IN ipoib_adapter_t* const p_adapter,
\r
1202 IN const ip_stat_sel_t stat_sel,
\r
1203 IN const size_t bytes OPTIONAL )
\r
1205 IPOIB_ENTER( IPOIB_DBG_STAT );
\r
1207 cl_spinlock_acquire( &p_adapter->send_stat_lock );
\r
1208 switch( stat_sel )
\r
1210 case IP_STAT_ERROR:
\r
1211 p_adapter->send_stats.comp.error++;
\r
1214 case IP_STAT_DROPPED:
\r
1215 p_adapter->send_stats.comp.dropped++;
\r
1218 case IP_STAT_UCAST_BYTES:
\r
1219 case IP_STAT_UCAST_FRAMES:
\r
1220 p_adapter->send_stats.comp.success++;
\r
1221 p_adapter->send_stats.ucast.frames++;
\r
1222 p_adapter->send_stats.ucast.bytes += bytes;
\r
1225 case IP_STAT_BCAST_BYTES:
\r
1226 case IP_STAT_BCAST_FRAMES:
\r
1227 p_adapter->send_stats.comp.success++;
\r
1228 p_adapter->send_stats.bcast.frames++;
\r
1229 p_adapter->send_stats.bcast.bytes += bytes;
\r
1232 case IP_STAT_MCAST_BYTES:
\r
1233 case IP_STAT_MCAST_FRAMES:
\r
1234 p_adapter->send_stats.comp.success++;
\r
1235 p_adapter->send_stats.mcast.frames++;
\r
1236 p_adapter->send_stats.mcast.bytes += bytes;
\r
1242 cl_spinlock_release( &p_adapter->send_stat_lock );
\r
1244 IPOIB_EXIT( IPOIB_DBG_STAT );
\r