[IPoIB] More SM reregister handling
authorftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 24 Apr 2006 23:29:31 +0000 (23:29 +0000)
committerftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 24 Apr 2006 23:29:31 +0000 (23:29 +0000)
- Avoid attempting to bring the IPoIB port up when a SM change event
is received while the link state is not active
- Add proper state transition before calling ipoib_port_up during SM
change handling.
- Only destroy multicast endpoints when the port goes down, just flush
the AVs from unicast endpoints

git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@323 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

ulp/ipoib/kernel/ipoib_adapter.c
ulp/ipoib/kernel/ipoib_port.c

index cd14196..af976df 100644 (file)
@@ -480,6 +480,7 @@ __ipoib_pnp_cb(
        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
@@ -507,6 +508,8 @@ __ipoib_pnp_cb(
        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
@@ -530,8 +533,7 @@ __ipoib_pnp_cb(
                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
@@ -568,7 +570,7 @@ __ipoib_pnp_cb(
                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
@@ -639,6 +641,12 @@ __ipoib_pnp_cb(
        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
@@ -652,7 +660,6 @@ __ipoib_pnp_cb(
                }\r
                cl_obj_unlock( &p_adapter->obj );\r
                \r
-               status = IB_SUCCESS;\r
                if( p_adapter->registering )\r
                        break;\r
 \r
@@ -670,6 +677,9 @@ __ipoib_pnp_cb(
                        /* 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
index f501530..593061c 100644 (file)
@@ -370,6 +370,10 @@ __endpt_mgr_remove(
        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
@@ -653,6 +657,8 @@ __port_destroying(
 \r
        ipoib_port_down( p_port );\r
 \r
+       __endpt_mgr_remove_all( p_port );\r
+\r
        IPOIB_EXIT( IPOIB_DBG_INIT );\r
 }\r
 \r
@@ -3869,33 +3875,98 @@ __endpt_mgr_destroy(
 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
@@ -3946,7 +4017,7 @@ ipoib_mac_to_gid(
        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
@@ -4830,8 +4901,8 @@ ipoib_port_down(
                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