ipoib_adapter_t *p_adapter;\r
ipoib_port_t *p_port;\r
ib_pnp_event_t old_state;\r
+ ib_pnp_port_rec_t *p_port_rec;\r
\r
IPOIB_ENTER( IPOIB_DBG_PNP );\r
\r
IPOIB_TRACE( IPOIB_DBG_INFO,\r
("p_pnp_rec->pnp_event = 0x%x\n",p_pnp_rec->pnp_event));\r
\r
+ p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec;\r
+\r
switch( p_pnp_rec->pnp_event )\r
{\r
case IB_PNP_PORT_ADD:\r
cl_obj_lock( &p_adapter->obj );\r
p_adapter->state = IB_PNP_PORT_ADD;\r
cl_obj_unlock( &p_adapter->obj );\r
- status = ipoib_create_port( p_adapter,\r
- (ib_pnp_port_rec_t*)p_pnp_rec, &p_port );\r
+ status = ipoib_create_port( p_adapter, p_port_rec, &p_port );\r
cl_obj_lock( &p_adapter->obj );\r
if( status != IB_SUCCESS )\r
{\r
cl_obj_lock( &p_adapter->obj );\r
p_adapter->state = IB_PNP_PORT_INIT;\r
cl_obj_unlock( &p_adapter->obj );\r
- ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );\r
+ ipoib_port_up( p_adapter->p_port, p_port_rec );\r
\r
status = IB_SUCCESS;\r
break;\r
case IB_PNP_SM_CHANGE:\r
case IB_PNP_GID_CHANGE:\r
case IB_PNP_LID_CHANGE:\r
+ status = IB_SUCCESS;\r
+\r
+ /* We ignore this event if the link is not active. */\r
+ if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE )\r
+ break;\r
+\r
cl_obj_lock( &p_adapter->obj );\r
old_state = p_adapter->state;\r
switch( old_state )\r
}\r
cl_obj_unlock( &p_adapter->obj );\r
\r
- status = IB_SUCCESS;\r
if( p_adapter->registering )\r
break;\r
\r
/* Fall through. */\r
\r
case IB_PNP_PORT_DOWN:\r
+ cl_obj_lock( &p_adapter->obj );\r
+ p_adapter->state = IB_PNP_PORT_INIT;\r
+ cl_obj_unlock( &p_adapter->obj );\r
ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );\r
}\r
break;\r
IN ipoib_port_t* const p_port,\r
IN ipoib_endpt_t* const p_endpt );\r
\r
+static void\r
+__endpt_mgr_reset_all(\r
+ IN ipoib_port_t* const p_port );\r
+\r
static inline NDIS_STATUS\r
__endpt_mgr_ref(\r
IN ipoib_port_t* const p_port,\r
\r
ipoib_port_down( p_port );\r
\r
+ __endpt_mgr_remove_all( p_port );\r
+\r
IPOIB_EXIT( IPOIB_DBG_INIT );\r
}\r
\r
static void\r
__endpt_mgr_remove_all(\r
IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+ \r
+ cl_obj_lock( &p_port->obj );\r
+ /* Wait for all readers to complete. */\r
+ while( p_port->endpt_rdr )\r
+ ;\r
+ /*\r
+ * We don't need to initiate destruction - this is called only\r
+ * from the __port_destroying function, and destruction cascades\r
+ * to all child objects. Just clear all the maps.\r
+ */\r
+ cl_qmap_remove_all( &p_port->endpt_mgr.mac_endpts );\r
+ cl_qmap_remove_all( &p_port->endpt_mgr.lid_endpts );\r
+ cl_fmap_remove_all( &p_port->endpt_mgr.gid_endpts );\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_mgr_reset_all(\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
\r
IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ cl_qlist_init( &mc_list );\r
\r
cl_obj_lock( &p_port->obj );\r
/* Wait for all readers to complete. */\r
while( p_port->endpt_rdr )\r
;\r
+\r
+ if( p_port->p_local_endpt )\r
+ {\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+ &p_port->p_local_endpt->mac_item );\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+ &p_port->p_local_endpt->gid_item );\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+ &p_port->p_local_endpt->lid_item );\r
+\r
+ cl_qlist_insert_head(\r
+ &mc_list, &p_port->p_local_endpt->mac_item.pool_item.list_item );\r
+\r
+ p_port->p_local_endpt = NULL;\r
+ }\r
+\r
p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
while( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
{\r
p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
- cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, p_item );\r
- cl_obj_unlock( &p_port->obj );\r
- cl_obj_destroy( &p_endpt->obj );\r
- cl_obj_lock( &p_port->obj );\r
- /* Wait for all readers to complete. */\r
- while( p_port->endpt_rdr )\r
- ;\r
- p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
+ p_item = cl_qmap_next( p_item );\r
+ if( p_endpt->h_mcast )\r
+ {\r
+ /*\r
+ * We destroy MC endpoints since they will get recreated\r
+ * when the port comes back up and we rejoin the MC groups.\r
+ */\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+ &p_endpt->mac_item );\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+ &p_endpt->gid_item );\r
+ if( p_endpt->dlid )\r
+ {\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+ &p_endpt->lid_item );\r
+ }\r
+ cl_qlist_insert_tail(\r
+ &mc_list, &p_endpt->mac_item.pool_item.list_item );\r
+ }\r
+ else if( p_endpt->h_av )\r
+ {\r
+ /* Destroy the AV for all other endpoints. */\r
+ p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
+ p_endpt->h_av = NULL;\r
+ }\r
}\r
- cl_qmap_remove_all( &p_port->endpt_mgr.lid_endpts );\r
- cl_fmap_remove_all( &p_port->endpt_mgr.gid_endpts );\r
cl_obj_unlock( &p_port->obj );\r
\r
+ /* Destroy all multicast endpoints now that we have released the lock. */\r
+ while( cl_qlist_count( &mc_list ) )\r
+ {\r
+ cl_obj_destroy( &PARENT_STRUCT( cl_qlist_remove_head( &mc_list ),\r
+ ipoib_endpt_t, mac_item.pool_item.list_item )->obj );\r
+ }\r
+\r
IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
}\r
\r
IN const mac_addr_t mac,\r
OUT ib_gid_t* p_gid )\r
{\r
- ipoib_endpt_t* p_endpt;\r
+ ipoib_endpt_t* p_endpt;\r
cl_map_item_t *p_item;\r
uint64_t key = 0;\r
\r
return;\r
}\r
\r
- /* Initiate cleanup of all endpoints */\r
- __endpt_mgr_remove_all( p_port );\r
+ /* Reset all endpoints so we don't flush our ARP cache. */\r
+ __endpt_mgr_reset_all( p_port );\r
\r
IPOIB_EXIT( IPOIB_DBG_INIT );\r
}\r