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
38 #include <complib/cl_init.h>
\r
41 #define ITEM_POOL_START 16
\r
42 #define ITEM_POOL_GROW 16
\r
45 /* IB Link speeds in 100bps */
\r
46 #define ONE_X_IN_100BPS 25000000
\r
47 #define FOUR_X_IN_100BPS 100000000
\r
48 #define TWELVE_X_IN_100BPS 300000000
\r
54 IN ipoib_adapter_t* const p_adapter );
\r
57 static ib_api_status_t
\r
59 IN ipoib_adapter_t* const p_adapter );
\r
63 __adapter_destroying(
\r
64 IN cl_obj_t* const p_obj );
\r
69 IN cl_obj_t* const p_obj );
\r
74 IN cl_obj_t* const p_obj );
\r
77 static ib_api_status_t
\r
79 IN ipoib_adapter_t* const p_adapter,
\r
80 IN ib_pnp_class_t flags );
\r
88 static ib_api_status_t
\r
90 IN ib_pnp_rec_t *p_pnp_rec );
\r
95 IN ipoib_adapter_t* const p_adapter );
\r
100 IN ipoib_adapter_t* const p_adapter );
\r
103 /* Leaves all mcast groups when port goes down. */
\r
106 IN ipoib_port_t* const p_port );
\r
109 ipoib_get_adapter_guids(
\r
110 IN NDIS_HANDLE* const h_adapter,
\r
111 IN OUT ipoib_adapter_t *p_adapter );
\r
114 ipoib_get_adapter_params(
\r
115 IN NDIS_HANDLE* const wrapper_config_context,
\r
116 OUT ipoib_params_t* const p_params );
\r
119 /* Implementation */
\r
121 ipoib_create_adapter(
\r
122 IN NDIS_HANDLE wrapper_config_context,
\r
123 IN void* const h_adapter,
\r
124 OUT ipoib_adapter_t** const pp_adapter )
\r
126 ipoib_adapter_t *p_adapter;
\r
127 ib_api_status_t status;
\r
128 cl_status_t cl_status;
\r
130 KLOCK_QUEUE_HANDLE hdl;
\r
132 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
134 if( !NT_SUCCESS( CL_INIT ) )
\r
136 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
137 ("cl_init failed.\n") );
\r
141 p_adapter = cl_zalloc( sizeof(ipoib_adapter_t) );
\r
145 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
146 ("Failed to allocate ipoib_adapter_t (%d bytes)",
\r
147 sizeof(ipoib_adapter_t)) );
\r
148 return IB_INSUFFICIENT_MEMORY;
\r
151 adapter_construct( p_adapter );
\r
153 p_adapter->h_adapter = h_adapter;
\r
155 p_adapter->p_ifc = cl_zalloc( sizeof(ib_al_ifc_t) );
\r
156 if( !p_adapter->p_ifc )
\r
158 __adapter_free( &p_adapter->obj );
\r
159 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
160 ("ipoib_create_adapter failed to alloc ipoib_ifc_t % bytes\n",
\r
161 sizeof(ib_al_ifc_t)) );
\r
162 return IB_INSUFFICIENT_MEMORY;
\r
165 /* Get the CA and port GUID from the bus driver. */
\r
166 status = ipoib_get_adapter_guids( h_adapter, p_adapter );
\r
167 if( status != NDIS_STATUS_SUCCESS )
\r
169 __adapter_free( &p_adapter->obj );
\r
170 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
171 ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );
\r
175 port_num = IPOIB_GET_PORT_NUM_FROM_GUID(p_adapter->guids.port_guid);
\r
177 IPOIB_TRACE( IPOIB_DBG_INFO,
\r
178 ("Port %d initializing\n", port_num) );
\r
180 /* Read configuration parameters. */
\r
181 status = ipoib_get_adapter_params( wrapper_config_context,
\r
182 &p_adapter->params );
\r
183 if( status != NDIS_STATUS_SUCCESS )
\r
185 __adapter_free( &p_adapter->obj );
\r
186 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
187 ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );
\r
191 cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC,
\r
192 __adapter_destroying, NULL, __adapter_free );
\r
193 if( cl_status != CL_SUCCESS )
\r
195 __adapter_free( &p_adapter->obj );
\r
196 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
197 ("cl_obj_init returned %s\n", cl_status_text[cl_status]) );
\r
201 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
\r
202 InsertHeadList( &g_ipoib.adapter_list, &p_adapter->entry );
\r
203 KeReleaseInStackQueuedSpinLock( &hdl );
\r
205 status = adapter_init( p_adapter );
\r
206 if( status != IB_SUCCESS )
\r
208 cl_obj_destroy( &p_adapter->obj );
\r
209 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
210 ("adapter_init returned %s.\n",
\r
211 p_adapter->p_ifc->get_err_str( status )) );
\r
215 *pp_adapter = p_adapter;
\r
217 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
223 ipoib_start_adapter(
\r
224 IN ipoib_adapter_t* const p_adapter )
\r
226 ib_api_status_t status;
\r
228 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
230 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_SYNC );
\r
232 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
238 ipoib_destroy_adapter(
\r
239 IN ipoib_adapter_t* const p_adapter )
\r
241 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
243 CL_ASSERT( p_adapter );
\r
246 * Flag the adapter as being removed. We use the IB_PNP_CA_REMOVE state
\r
247 * for this purpose. Note that we protect this state change with both the
\r
248 * mutex and the lock. The mutex provides synchronization as a whole
\r
249 * between destruction and AL callbacks (PnP, Query, Destruction).
\r
250 * The lock provides protection
\r
252 cl_mutex_acquire( &p_adapter->mutex );
\r
253 cl_obj_lock( &p_adapter->obj );
\r
254 p_adapter->state = IB_PNP_PORT_REMOVE;
\r
255 cl_obj_unlock( &p_adapter->obj );
\r
258 * Clear the pointer to the port object since the object destruction
\r
259 * will cascade to child objects. This prevents potential duplicate
\r
260 * destruction (or worse, stale pointer usage).
\r
262 p_adapter->p_port = NULL;
\r
264 cl_mutex_release( &p_adapter->mutex );
\r
266 cl_obj_destroy( &p_adapter->obj );
\r
268 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
274 IN ipoib_adapter_t* const p_adapter )
\r
276 cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );
\r
277 cl_spinlock_construct( &p_adapter->send_stat_lock );
\r
278 cl_spinlock_construct( &p_adapter->recv_stat_lock );
\r
279 cl_qpool_construct( &p_adapter->item_pool );
\r
280 cl_mutex_construct( &p_adapter->mutex );
\r
281 cl_vector_construct( &p_adapter->ip_vector );
\r
283 cl_perf_construct( &p_adapter->perf );
\r
285 p_adapter->state = IB_PNP_PORT_ADD;
\r
286 p_adapter->rate = FOUR_X_IN_100BPS;
\r
290 static ib_api_status_t
\r
292 IN ipoib_adapter_t* const p_adapter )
\r
294 cl_status_t cl_status;
\r
295 ib_api_status_t status;
\r
297 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
299 cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );
\r
300 if( cl_status != CL_SUCCESS )
\r
302 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
303 ("cl_perf_init returned %s\n", cl_status_text[cl_status]) );
\r
307 cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );
\r
308 if( cl_status != CL_SUCCESS )
\r
310 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
311 ("cl_spinlock_init returned %s\n", cl_status_text[cl_status]) );
\r
315 cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );
\r
316 if( cl_status != CL_SUCCESS )
\r
318 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
319 ("cl_spinlock_init returned %s\n", cl_status_text[cl_status]) );
\r
323 cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,
\r
324 ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );
\r
325 if( cl_status != CL_SUCCESS )
\r
327 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
328 ("cl_qpool_init returned %s\n", cl_status_text[cl_status]) );
\r
332 cl_status = cl_mutex_init( &p_adapter->mutex );
\r
333 if( cl_status != CL_SUCCESS )
\r
335 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
336 ("cl_mutex_init returned %s\n", cl_status_text[cl_status]) );
\r
340 /* We manually manage the size and capacity of the vector. */
\r
341 cl_status = cl_vector_init( &p_adapter->ip_vector, 0,
\r
342 0, sizeof(net_address_item_t), NULL, NULL, p_adapter );
\r
343 if( cl_status != CL_SUCCESS )
\r
345 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
346 ("cl_vector_init for ip_vector returned %s\n",
\r
347 CL_STATUS_MSG(cl_status)) );
\r
351 /* Validate the port GUID and generate the MAC address. */
\r
353 ipoib_mac_from_guid( p_adapter->guids.port_guid, &p_adapter->mac );
\r
354 if( status != IB_SUCCESS )
\r
356 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
357 ("ipoib_mac_from_guid returned %s\n",
\r
358 p_adapter->p_ifc->get_err_str( status )) );
\r
363 status = p_adapter->p_ifc->open_al( &p_adapter->h_al );
\r
364 if( status != IB_SUCCESS )
\r
366 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
367 ("ib_open_al returned %s\n",
\r
368 p_adapter->p_ifc->get_err_str( status )) );
\r
372 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
377 static ib_api_status_t
\r
379 IN ipoib_adapter_t* const p_adapter,
\r
380 IN ib_pnp_class_t flags )
\r
382 ib_api_status_t status;
\r
383 ib_pnp_req_t pnp_req;
\r
385 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
387 CL_ASSERT( !p_adapter->h_pnp );
\r
389 /* Register for PNP events. */
\r
390 cl_memclr( &pnp_req, sizeof(pnp_req) );
\r
391 pnp_req.pnp_class = IB_PNP_PORT | flags;
\r
393 * Context is the cl_obj of the adapter to allow passing cl_obj_deref
\r
396 pnp_req.pnp_context = &p_adapter->obj;
\r
397 pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;
\r
398 status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );
\r
399 if( status != IB_SUCCESS )
\r
401 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
402 ("ib_reg_pnp returned %s\n",
\r
403 p_adapter->p_ifc->get_err_str( status )) );
\r
407 * Reference the adapter on behalf of the PNP registration.
\r
408 * This allows the destruction to block until the PNP deregistration
\r
411 cl_obj_ref( &p_adapter->obj );
\r
413 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
419 __adapter_destroying(
\r
420 IN cl_obj_t* const p_obj )
\r
422 ipoib_adapter_t *p_adapter;
\r
423 KLOCK_QUEUE_HANDLE hdl;
\r
425 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
427 p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );
\r
430 * The adapter's object will be dereferenced when the deregistration
\r
431 * completes. No need to lock here since all PnP related API calls
\r
432 * are driven by NDIS (via the Init/Reset/Destroy paths).
\r
434 if( p_adapter->h_pnp )
\r
436 p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, cl_obj_deref );
\r
437 p_adapter->h_pnp = NULL;
\r
440 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
\r
441 ASSERT( !IsListEmpty( &g_ipoib.adapter_list ) );
\r
442 RemoveEntryList( &p_adapter->entry );
\r
443 KeReleaseInStackQueuedSpinLock( &hdl );
\r
445 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
451 IN cl_obj_t* const p_obj )
\r
453 ipoib_adapter_t *p_adapter;
\r
455 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
457 p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );
\r
459 if( p_adapter->p_ifc )
\r
461 if( p_adapter->h_al )
\r
462 p_adapter->p_ifc->close_al( p_adapter->h_al );
\r
464 cl_free( p_adapter->p_ifc );
\r
467 cl_vector_destroy( &p_adapter->ip_vector );
\r
468 cl_qpool_destroy( &p_adapter->item_pool );
\r
469 cl_spinlock_destroy( &p_adapter->recv_stat_lock );
\r
470 cl_spinlock_destroy( &p_adapter->send_stat_lock );
\r
471 cl_mutex_destroy( &p_adapter->mutex );
\r
472 cl_obj_deinit( p_obj );
\r
474 cl_perf_destroy( &p_adapter->perf, TRUE );
\r
476 cl_free( p_adapter );
\r
480 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
484 static ib_api_status_t
\r
486 IN ib_pnp_rec_t *p_pnp_rec )
\r
488 ib_api_status_t status;
\r
489 ipoib_adapter_t *p_adapter;
\r
490 ib_pnp_event_t old_state;
\r
492 IPOIB_ENTER( IPOIB_DBG_PNP );
\r
494 CL_ASSERT( p_pnp_rec );
\r
497 PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );
\r
499 CL_ASSERT( p_adapter );
\r
501 /* Synchronize with destruction */
\r
502 cl_mutex_acquire( &p_adapter->mutex );
\r
503 cl_obj_lock( &p_adapter->obj );
\r
504 old_state = p_adapter->state;
\r
505 cl_obj_unlock( &p_adapter->obj );
\r
506 if( old_state == IB_PNP_PORT_REMOVE )
\r
508 cl_mutex_release( &p_adapter->mutex );
\r
509 IPOIB_TRACE_EXIT( IPOIB_DBG_PNP,
\r
510 ("Aborting - Adapter destroying.\n") );
\r
511 return IB_NOT_DONE;
\r
514 IPOIB_TRACE( IPOIB_DBG_INFO,
\r
515 ("p_pnp_rec->pnp_event = 0x%x\n",p_pnp_rec->pnp_event));
\r
517 switch( p_pnp_rec->pnp_event )
\r
519 case IB_PNP_PORT_ADD:
\r
520 CL_ASSERT( !p_pnp_rec->context );
\r
521 /* Only process our port GUID. */
\r
522 if( p_pnp_rec->guid != p_adapter->guids.port_guid )
\r
524 status = IB_NOT_DONE;
\r
528 /* Don't process if we're destroying. */
\r
529 if( p_adapter->obj.state == CL_DESTROYING )
\r
531 status = IB_NOT_DONE;
\r
535 CL_ASSERT( !p_adapter->p_port );
\r
536 /* Allocate all IB resources. */
\r
537 cl_obj_lock( &p_adapter->obj );
\r
538 p_adapter->state = IB_PNP_PORT_ADD;
\r
539 cl_obj_unlock( &p_adapter->obj );
\r
540 status = ipoib_create_port( p_adapter,
\r
541 (ib_pnp_port_rec_t*)p_pnp_rec, &p_adapter->p_port );
\r
542 if( status != IB_SUCCESS )
\r
544 cl_obj_lock( &p_adapter->obj );
\r
545 p_adapter->state = old_state;
\r
546 cl_obj_unlock( &p_adapter->obj );
\r
547 p_adapter->hung = TRUE;
\r
551 p_pnp_rec->context = p_adapter->p_port;
\r
554 case IB_PNP_PORT_REMOVE:
\r
555 /* Release all IB resources. */
\r
556 CL_ASSERT( p_pnp_rec->context );
\r
558 cl_obj_lock( &p_adapter->obj );
\r
559 p_adapter->state = IB_PNP_PORT_REMOVE;
\r
560 cl_obj_unlock( &p_adapter->obj );
\r
561 ipoib_port_destroy( p_adapter->p_port );
\r
562 p_adapter->p_port = NULL;
\r
563 p_pnp_rec->context = NULL;
\r
564 status = IB_SUCCESS;
\r
567 case IB_PNP_PORT_ACTIVE:
\r
568 /* Join multicast groups and put QP in RTS. */
\r
569 CL_ASSERT( p_pnp_rec->context );
\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_INIT:
\r
577 case IB_PNP_PORT_ARMED:
\r
578 case IB_PNP_PORT_DOWN:
\r
579 /* Leave multicast groups. */
\r
580 CL_ASSERT( p_pnp_rec->context );
\r
582 cl_obj_lock( &p_adapter->obj );
\r
583 old_state = p_adapter->state;
\r
584 p_adapter->state = IB_PNP_PORT_DOWN;
\r
585 cl_obj_unlock( &p_adapter->obj );
\r
586 status = IB_SUCCESS;
\r
588 switch( old_state )
\r
590 case IB_PNP_PORT_ACTIVE:
\r
591 NdisMIndicateStatus( p_adapter->h_adapter,
\r
592 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );
\r
593 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
595 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link DOWN!\n") );
\r
597 ipoib_port_down( p_adapter->p_port );
\r
600 case IB_PNP_PORT_ADD:
\r
601 /* If we were initializing, we might have pended some OIDs. */
\r
602 ipoib_resume_oids( p_adapter );
\r
603 NdisMIndicateStatus( p_adapter->h_adapter,
\r
604 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );
\r
605 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
613 case IB_PNP_REG_COMPLETE:
\r
614 if( p_adapter->hung )
\r
616 p_adapter->hung = FALSE;
\r
617 NdisMResetComplete(
\r
618 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );
\r
620 status = IB_SUCCESS;
\r
624 IPOIB_TRACE( IPOIB_DBG_INFO,
\r
625 ("IPOIB: Received unhandled PnP event 0x%x\n",
\r
626 p_pnp_rec->pnp_event) );
\r
627 /* Fall through. */
\r
628 case IB_PNP_PKEY_CHANGE:
\r
629 case IB_PNP_SM_CHANGE:
\r
630 case IB_PNP_GID_CHANGE:
\r
631 case IB_PNP_LID_CHANGE:
\r
632 p_adapter->hung = TRUE;
\r
633 status = IB_SUCCESS;
\r
637 cl_mutex_release( &p_adapter->mutex );
\r
639 IPOIB_EXIT( IPOIB_DBG_PNP );
\r
644 /* Joins/leaves mcast groups based on currently programmed mcast MACs. */
\r
646 ipoib_refresh_mcast(
\r
647 IN ipoib_adapter_t* const p_adapter,
\r
648 IN mac_addr_t* const p_mac_array,
\r
649 IN const uint8_t num_macs )
\r
652 ipoib_port_t *p_port = NULL;
\r
654 IPOIB_ENTER( IPOIB_DBG_MCAST );
\r
655 cl_obj_lock( &p_adapter->obj );
\r
656 if( p_adapter->state == IB_PNP_PORT_ACTIVE )
\r
658 p_port = p_adapter->p_port;
\r
659 cl_obj_ref( &p_port->obj );
\r
661 cl_obj_unlock( &p_adapter->obj );
\r
665 /* Purge old entries. */
\r
666 for( i = 0; i < p_adapter->mcast_array_size; i++ )
\r
668 for( j = 0; j < num_macs; j++ )
\r
670 if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],
\r
671 sizeof(mac_addr_t) ) )
\r
676 if( j != num_macs )
\r
679 ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );
\r
682 /* Add new entries */
\r
683 for( i = 0; i < num_macs; i++ )
\r
685 for( j = 0; j < p_adapter->mcast_array_size; j++ )
\r
687 if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],
\r
688 sizeof(mac_addr_t) ) )
\r
694 if( j != p_adapter->mcast_array_size )
\r
697 ipoib_port_join_mcast( p_port, p_mac_array[i] );
\r
701 /* Copy the MAC array. */
\r
702 NdisMoveMemory( p_adapter->mcast_array, p_mac_array,
\r
703 num_macs * sizeof(mac_addr_t) );
\r
704 p_adapter->mcast_array_size = num_macs;
\r
707 cl_obj_deref( &p_port->obj );
\r
709 IPOIB_EXIT( IPOIB_DBG_MCAST );
\r
714 ipoib_reset_adapter(
\r
715 IN ipoib_adapter_t* const p_adapter )
\r
717 ib_api_status_t status;
\r
719 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
721 if( p_adapter->h_pnp )
\r
723 status = p_adapter->p_ifc->dereg_pnp(
\r
724 p_adapter->h_pnp, __ipoib_pnp_dereg );
\r
725 p_adapter->h_pnp = NULL;
\r
726 if( status == IB_SUCCESS )
\r
727 status = IB_NOT_DONE;
\r
731 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );
\r
732 if( status == IB_SUCCESS )
\r
733 p_adapter->hung = FALSE;
\r
736 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
745 ipoib_adapter_t* p_adapter;
\r
746 ib_api_status_t status;
\r
747 ib_pnp_event_t state;
\r
749 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
751 p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );
\r
753 /* Synchronize with destruction */
\r
754 cl_mutex_acquire( &p_adapter->mutex );
\r
756 cl_obj_lock( &p_adapter->obj );
\r
758 CL_ASSERT( !p_adapter->h_pnp );
\r
760 if( p_adapter->state != IB_PNP_PORT_REMOVE )
\r
761 p_adapter->state = IB_PNP_PORT_ADD;
\r
763 state = p_adapter->state;
\r
765 cl_obj_unlock( &p_adapter->obj );
\r
767 /* Destroy the current port instance if it still exists. */
\r
768 if( p_adapter->p_port )
\r
770 ipoib_port_destroy( p_adapter->p_port );
\r
771 p_adapter->p_port = NULL;
\r
773 /* Complete any pending OIDs. */
\r
774 ipoib_resume_oids( p_adapter );
\r
776 if( state != IB_PNP_PORT_REMOVE )
\r
778 status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );
\r
779 if( status != IB_SUCCESS )
\r
781 p_adapter->hung = FALSE;
\r
782 IPOIB_TRACE( IPOIB_DBG_ERROR,
\r
783 ("__ipoib_pnp_reg returned %s\n",
\r
784 p_adapter->p_ifc->get_err_str( status )) );
\r
785 NdisMResetComplete(
\r
786 p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );
\r
791 p_adapter->hung = FALSE;
\r
792 NdisMResetComplete(
\r
793 p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );
\r
794 status = IB_SUCCESS;
\r
797 /* Dereference the adapter since the previous registration is now gone. */
\r
798 cl_obj_deref( &p_adapter->obj );
\r
800 cl_mutex_release( &p_adapter->mutex );
\r
802 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
808 IN ipoib_adapter_t* const p_adapter,
\r
809 IN const uint8_t link_width )
\r
811 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
813 cl_obj_lock( &p_adapter->obj );
\r
814 /* Set the link speed based on the IB link speed (1x vs 4x, etc). */
\r
815 switch( link_width )
\r
817 case IB_LINK_WIDTH_ACTIVE_1X:
\r
818 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 2.5Gbps\n") );
\r
819 p_adapter->rate = ONE_X_IN_100BPS;
\r
822 case IB_LINK_WIDTH_ACTIVE_4X:
\r
823 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 10Gbps\n") );
\r
824 p_adapter->rate = FOUR_X_IN_100BPS;
\r
827 case IB_LINK_WIDTH_ACTIVE_12X:
\r
828 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 30Gbps\n") );
\r
829 p_adapter->rate = TWELVE_X_IN_100BPS;
\r
833 IPOIB_TRACE( IPOIB_DBG_INFO, ("Invalid rate.\n") );
\r
834 p_adapter->rate = 0;
\r
836 cl_obj_unlock( &p_adapter->obj );
\r
838 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
844 IN ipoib_adapter_t* const p_adapter )
\r
846 ib_pnp_event_t old_state;
\r
849 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
851 cl_obj_lock( &p_adapter->obj );
\r
852 old_state = p_adapter->state;
\r
854 /* Change the state to indicate that we are now connected and live. */
\r
855 if( old_state != IB_PNP_PORT_REMOVE )
\r
856 p_adapter->state = IB_PNP_PORT_ACTIVE;
\r
858 cl_obj_unlock( &p_adapter->obj );
\r
861 * If we had a pending OID request for OID_GEN_LINK_SPEED,
\r
864 switch( old_state )
\r
866 case IB_PNP_PORT_ADD:
\r
867 ipoib_reg_addrs( p_adapter );
\r
868 /* Fall through. */
\r
870 case IB_PNP_PORT_REMOVE:
\r
871 ipoib_resume_oids( p_adapter );
\r
875 /* Join all programmed multicast groups. */
\r
876 for( i = 0; i < p_adapter->mcast_array_size; i++ )
\r
878 ipoib_port_join_mcast( p_adapter->p_port, p_adapter->mcast_array[i] );
\r
881 /* Register all existing addresses. */
\r
882 ipoib_reg_addrs( p_adapter );
\r
884 /* Now that we're in the broadcast group, notify that we have a link. */
\r
885 IPOIB_TRACE( IPOIB_DBG_INFO, ("Link UP!\n") );
\r
886 NdisMIndicateStatus( p_adapter->h_adapter, NDIS_STATUS_MEDIA_CONNECT,
\r
888 NdisMIndicateStatusComplete( p_adapter->h_adapter );
\r
891 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
896 ipoib_get_recv_stat(
\r
897 IN ipoib_adapter_t* const p_adapter,
\r
898 IN const ip_stat_sel_t stat_sel,
\r
899 IN pending_oid_t* const p_oid_info )
\r
903 IPOIB_ENTER( IPOIB_DBG_INFO );
\r
905 CL_ASSERT( p_adapter );
\r
907 cl_spinlock_acquire( &p_adapter->recv_stat_lock );
\r
910 case IP_STAT_SUCCESS:
\r
911 stat = p_adapter->recv_stats.comp.success;
\r
914 case IP_STAT_ERROR:
\r
915 stat = p_adapter->recv_stats.comp.error;
\r
918 case IP_STAT_DROPPED:
\r
919 stat = p_adapter->recv_stats.comp.dropped;
\r
922 case IP_STAT_UCAST_BYTES:
\r
923 stat = p_adapter->recv_stats.ucast.bytes;
\r
926 case IP_STAT_UCAST_FRAMES:
\r
927 stat = p_adapter->recv_stats.ucast.frames;
\r
930 case IP_STAT_BCAST_BYTES:
\r
931 stat = p_adapter->recv_stats.bcast.bytes;
\r
934 case IP_STAT_BCAST_FRAMES:
\r
935 stat = p_adapter->recv_stats.bcast.frames;
\r
938 case IP_STAT_MCAST_BYTES:
\r
939 stat = p_adapter->recv_stats.mcast.bytes;
\r
942 case IP_STAT_MCAST_FRAMES:
\r
943 stat = p_adapter->recv_stats.mcast.frames;
\r
949 cl_spinlock_release( &p_adapter->recv_stat_lock );
\r
951 *p_oid_info->p_bytes_needed = sizeof(uint64_t);
\r
953 if( p_oid_info->buf_len >= sizeof(uint64_t) )
\r
955 *((uint64_t*)p_oid_info->p_buf) = stat;
\r
956 *p_oid_info->p_bytes_used = sizeof(uint64_t);
\r
958 else if( p_oid_info->buf_len >= sizeof(uint32_t) )
\r
960 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;
\r
961 *p_oid_info->p_bytes_used = sizeof(uint32_t);
\r
965 *p_oid_info->p_bytes_used = 0;
\r
966 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
967 return NDIS_STATUS_INVALID_LENGTH;
\r
970 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
971 return NDIS_STATUS_SUCCESS;
\r
976 ipoib_inc_recv_stat(
\r
977 IN ipoib_adapter_t* const p_adapter,
\r
978 IN const ip_stat_sel_t stat_sel,
\r
979 IN const size_t bytes OPTIONAL )
\r
981 IPOIB_ENTER( IPOIB_DBG_INFO );
\r
983 cl_spinlock_acquire( &p_adapter->recv_stat_lock );
\r
986 case IP_STAT_ERROR:
\r
987 p_adapter->recv_stats.comp.error++;
\r
990 case IP_STAT_DROPPED:
\r
991 p_adapter->recv_stats.comp.dropped++;
\r
994 case IP_STAT_UCAST_BYTES:
\r
995 case IP_STAT_UCAST_FRAMES:
\r
996 p_adapter->recv_stats.comp.success++;
\r
997 p_adapter->recv_stats.ucast.frames++;
\r
998 p_adapter->recv_stats.ucast.bytes += bytes;
\r
1001 case IP_STAT_BCAST_BYTES:
\r
1002 case IP_STAT_BCAST_FRAMES:
\r
1003 p_adapter->recv_stats.comp.success++;
\r
1004 p_adapter->recv_stats.bcast.frames++;
\r
1005 p_adapter->recv_stats.bcast.bytes += bytes;
\r
1008 case IP_STAT_MCAST_BYTES:
\r
1009 case IP_STAT_MCAST_FRAMES:
\r
1010 p_adapter->recv_stats.comp.success++;
\r
1011 p_adapter->recv_stats.mcast.frames++;
\r
1012 p_adapter->recv_stats.mcast.bytes += bytes;
\r
1018 cl_spinlock_release( &p_adapter->recv_stat_lock );
\r
1020 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
1024 ipoib_get_send_stat(
\r
1025 IN ipoib_adapter_t* const p_adapter,
\r
1026 IN const ip_stat_sel_t stat_sel,
\r
1027 IN pending_oid_t* const p_oid_info )
\r
1031 IPOIB_ENTER( IPOIB_DBG_INFO );
\r
1033 CL_ASSERT( p_adapter );
\r
1035 cl_spinlock_acquire( &p_adapter->send_stat_lock );
\r
1036 switch( stat_sel )
\r
1038 case IP_STAT_SUCCESS:
\r
1039 stat = p_adapter->send_stats.comp.success;
\r
1042 case IP_STAT_ERROR:
\r
1043 stat = p_adapter->send_stats.comp.error;
\r
1046 case IP_STAT_DROPPED:
\r
1047 stat = p_adapter->send_stats.comp.dropped;
\r
1050 case IP_STAT_UCAST_BYTES:
\r
1051 stat = p_adapter->send_stats.ucast.bytes;
\r
1054 case IP_STAT_UCAST_FRAMES:
\r
1055 stat = p_adapter->send_stats.ucast.frames;
\r
1058 case IP_STAT_BCAST_BYTES:
\r
1059 stat = p_adapter->send_stats.bcast.bytes;
\r
1062 case IP_STAT_BCAST_FRAMES:
\r
1063 stat = p_adapter->send_stats.bcast.frames;
\r
1066 case IP_STAT_MCAST_BYTES:
\r
1067 stat = p_adapter->send_stats.mcast.bytes;
\r
1070 case IP_STAT_MCAST_FRAMES:
\r
1071 stat = p_adapter->send_stats.mcast.frames;
\r
1077 cl_spinlock_release( &p_adapter->send_stat_lock );
\r
1079 *p_oid_info->p_bytes_needed = sizeof(uint64_t);
\r
1081 if( p_oid_info->buf_len >= sizeof(uint64_t) )
\r
1083 *((uint64_t*)p_oid_info->p_buf) = stat;
\r
1084 *p_oid_info->p_bytes_used = sizeof(uint64_t);
\r
1086 else if( p_oid_info->buf_len >= sizeof(uint32_t) )
\r
1088 *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;
\r
1089 *p_oid_info->p_bytes_used = sizeof(uint32_t);
\r
1093 *p_oid_info->p_bytes_used = 0;
\r
1094 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
1095 return NDIS_STATUS_INVALID_LENGTH;
\r
1098 IPOIB_EXIT( IPOIB_DBG_INFO );
\r
1099 return NDIS_STATUS_SUCCESS;
\r
1104 ipoib_inc_send_stat(
\r
1105 IN ipoib_adapter_t* const p_adapter,
\r
1106 IN const ip_stat_sel_t stat_sel,
\r
1107 IN const size_t bytes OPTIONAL )
\r
1109 IPOIB_ENTER( IPOIB_DBG_INFO );
\r
1111 cl_spinlock_acquire( &p_adapter->send_stat_lock );
\r
1112 switch( stat_sel )
\r
1114 case IP_STAT_ERROR:
\r
1115 p_adapter->send_stats.comp.error++;
\r
1118 case IP_STAT_DROPPED:
\r
1119 p_adapter->send_stats.comp.dropped++;
\r
1122 case IP_STAT_UCAST_BYTES:
\r
1123 case IP_STAT_UCAST_FRAMES:
\r
1124 p_adapter->send_stats.comp.success++;
\r
1125 p_adapter->send_stats.ucast.frames++;
\r
1126 p_adapter->send_stats.ucast.bytes += bytes;
\r
1129 case IP_STAT_BCAST_BYTES:
\r
1130 case IP_STAT_BCAST_FRAMES:
\r
1131 p_adapter->send_stats.comp.success++;
\r
1132 p_adapter->send_stats.bcast.frames++;
\r
1133 p_adapter->send_stats.bcast.bytes += bytes;
\r
1136 case IP_STAT_MCAST_BYTES:
\r
1137 case IP_STAT_MCAST_FRAMES:
\r
1138 p_adapter->send_stats.comp.success++;
\r
1139 p_adapter->send_stats.mcast.frames++;
\r
1140 p_adapter->send_stats.mcast.bytes += bytes;
\r
1146 cl_spinlock_release( &p_adapter->send_stat_lock );
\r
1148 IPOIB_EXIT( IPOIB_DBG_INFO );
\r