IN void* context );\r
\r
\r
+static void\r
+__ipoib_adapter_reset(\r
+ IN void* context);\r
+\r
+\r
static ib_api_status_t\r
__ipoib_pnp_cb(\r
IN ib_pnp_rec_t *p_pnp_rec );\r
\r
\r
-static void\r
-ipoib_destroy_port(\r
- IN ipoib_adapter_t* const p_adapter );\r
-\r
-\r
void\r
ipoib_join_mcast(\r
IN ipoib_adapter_t* const p_adapter );\r
cl_spinlock_construct( &p_adapter->recv_stat_lock );\r
cl_qpool_construct( &p_adapter->item_pool );\r
KeInitializeMutex( &p_adapter->mutex, 0 );\r
+\r
+ cl_thread_construct(&p_adapter->destroy_thread);\r
+ \r
cl_vector_construct( &p_adapter->ip_vector );\r
\r
cl_perf_construct( &p_adapter->perf );\r
return IB_ERROR;\r
}\r
\r
+\r
/* Validate the port GUID and generate the MAC address. */\r
status =\r
ipoib_mac_from_guid( p_adapter->guids.port_guid, &p_adapter->mac );\r
return status;\r
}\r
\r
+ \r
+ \r
/* Open AL. */\r
status = p_adapter->p_ifc->open_al( &p_adapter->h_al );\r
if( status != IB_SUCCESS )\r
CL_ASSERT( !p_adapter->registering );\r
\r
p_adapter->registering = TRUE;\r
-\r
+ \r
/* Register for PNP events. */\r
cl_memclr( &pnp_req, sizeof(pnp_req) );\r
pnp_req.pnp_class = IB_PNP_PORT | flags;\r
IN void* context )\r
{\r
ipoib_adapter_t* p_adapter;\r
- ipoib_port_t* p_port;\r
- ib_api_status_t status;\r
- ib_pnp_event_t state;\r
\r
IPOIB_ENTER( IPOIB_DBG_INIT );\r
\r
p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );\r
\r
+ cl_thread_init(&p_adapter->destroy_thread, __ipoib_adapter_reset, (void*)p_adapter, "destroy_thread");\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+}\r
+\r
+static void\r
+__ipoib_adapter_reset(\r
+ IN void* context)\r
+{\r
+\r
+ ipoib_adapter_t *p_adapter;\r
+ ipoib_port_t *p_port;\r
+ ib_api_status_t status;\r
+ ib_pnp_event_t state;\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_adapter = (ipoib_adapter_t*)context;\r
+ \r
/* Synchronize with destruction */\r
KeWaitForMutexObject(\r
&p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
p_port->p_adapter->h_al, p_endpt->h_query );\r
p_endpt->h_query = NULL;\r
}\r
+\r
+ /* Leave the multicast group if it exists. */\r
+ if( p_endpt->h_mcast )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("Leaving MCast group\n") );\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, ipoib_leave_mcast_cb );\r
+ }\r
+ \r
cl_obj_unlock( p_obj );\r
\r
IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
p_port = __endpt_parent( p_endpt );\r
\r
- /* Leave the multicast group if it exists. */\r
- if( p_endpt->h_mcast )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("Leaving MCast group\n") );\r
- p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, NULL );\r
- }\r
-\r
/* Destroy the AV if it exists. */\r
if( p_endpt->h_av )\r
p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
__mcast_cb(\r
IN ib_mcast_rec_t *p_mcast_rec );\r
\r
+void\r
+__leave_error_mcast_cb(\r
+ IN void *context );\r
+\r
\r
static intn_t\r
__gid_cmp(\r
__endpt_mgr_construct( p_port );\r
\r
KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE );\r
-\r
+ KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE );\r
+ \r
IPOIB_EXIT( IPOIB_DBG_INIT );\r
}\r
\r
IN ipoib_port_t* const p_port )\r
{\r
cl_map_item_t *p_item;\r
- ipoib_endpt_t *p_endpt;\r
- cl_qlist_t mc_list;\r
+ ipoib_endpt_t *p_endpt;\r
+ cl_qlist_t mc_list;\r
+ uint32_t local_exist = 0;\r
+\r
\r
IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
\r
\r
cl_qlist_insert_head(\r
&mc_list, &p_port->p_local_endpt->mac_item.pool_item.list_item );\r
+ local_exist = 1;\r
\r
p_port->p_local_endpt = NULL;\r
}\r
}\r
\r
}\r
+\r
cl_obj_unlock( &p_port->obj );\r
\r
+\r
+ if(cl_qlist_count( &mc_list ) - local_exist)\r
+ {\r
+ p_port->mcast_cnt = (uint32_t)cl_qlist_count( &mc_list ) - local_exist;\r
+ }\r
+ else\r
+ {\r
+ p_port->mcast_cnt = 0;\r
+ KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
+ } \r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt - local_exist));\r
+\r
/* Destroy all multicast endpoints now that we have released the lock. */\r
while( cl_qlist_count( &mc_list ) )\r
{\r
return;\r
}\r
\r
+ KeResetEvent(&p_port->leave_mcast_event);\r
+\r
/* Reset all endpoints so we don't flush our ARP cache. */\r
__endpt_mgr_reset_all( p_port );\r
\r
+ KeWaitForSingleObject(\r
+ &p_port->leave_mcast_event, Executive, KernelMode, FALSE, NULL );\r
+ \r
cl_obj_lock( &p_port->p_adapter->obj );\r
ipoib_dereg_addrs( p_port->p_adapter );\r
cl_obj_unlock( &p_port->p_adapter->obj );\r
{\r
cl_obj_unlock( &p_port->obj );\r
if( p_mcast_rec->status == IB_SUCCESS )\r
- p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, NULL );\r
\r
+ {\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+ }\r
KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
ipoib_port_deref( p_port, ref_bcast_inv_state );\r
IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
("__endpt_mgr_add_bcast returned %s\n",\r
p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- status = p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, NULL );\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ status = p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
CL_ASSERT( status == IB_SUCCESS );\r
goto err;\r
}\r
{\r
cl_obj_unlock( &p_port->obj );\r
if( p_mcast_rec->status == IB_SUCCESS )\r
- p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, NULL );\r
\r
+ {\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+ }\r
ipoib_port_deref( p_port, ref_mcast_inv_state );\r
IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
("Invalid state - Aborting.\n") );\r
cl_obj_unlock( &p_port->obj );\r
IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
("Failed to find endpoint for update.\n") );\r
- p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, NULL );\r
+\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
ipoib_port_deref( p_port, ref_mcast_no_endpt );\r
IPOIB_EXIT( IPOIB_DBG_MCAST );\r
return;\r
\r
IPOIB_EXIT( IPOIB_DBG_MCAST );\r
}\r
+\r
+\r
+void\r
+ipoib_leave_mcast_cb(\r
+ IN void *context )\r
+{\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+ p_port = (ipoib_port_t* __ptr64)context;\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt));\r
+ \r
+ ipoib_port_deref( p_port, ref_leave_mcast);\r
+ cl_atomic_dec( &p_port->mcast_cnt);\r
+ \r
+ if(0 == p_port->mcast_cnt)\r
+ {\r
+ KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
+ }\r
+ \r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+ ("Leav mcast callback deref ipoib_port \n") );\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+\r
+void\r
+__leave_error_mcast_cb(\r
+ IN void *context )\r
+{\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+ p_port = (ipoib_port_t* __ptr64)context;\r
+\r
+ ipoib_port_deref( p_port, ref_leave_mcast);\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+ ("Leav mcast callback deref ipoib_port \n") );\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r