[IBAL] Summary: Ill-defined mechanism of event propagation.[mlnx: 4412]
authorleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 2 Jun 2009 17:32:41 +0000 (17:32 +0000)
committerleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 2 Jun 2009 17:32:41 +0000 (17:32 +0000)
Bug description and reproduction:
1. Connect to machines (A and B) via IB switch
2. Run subnet manager (say, opensm) on B
3. Kill opensm and clear arp tables
4. Rerun opensm - ping will not longer work
5. That's because new opensm instance will clear old multicast groups, and side A will be not aware about opensm restart and will not request to join new MCAST group

Explanations:
There are 2 types of events relevant in our case: PnP and AE.
The problem had happened due to:
1. During opensm restart, port will generate AE event: IB_EVENT_LID_CHANGE or (in other cases)  IB_EVENT_CLIENT_REREGISTER
These events will be generated even in the case when SM was restarted, but LID will not actually change.

2. All PnP events were handled properly; but these events were mapped to IB_AE_FATAL
This patch fixes it and maps IB_EVENT_* events to appropriate IB_AE_* events and then to IB_PNP_* events

3. unction force_smi_poll() will now update it's subscribers about LID change event iff LID was changed.
So, we still have the problem when opensm was restarted and no one of the port attributes was changed.

This patch generated appropriate IB_PNP event to resolve this issue.

Signed off by: Xalex

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

core/al/al_ci_ca.h
core/al/al_ci_ca_shared.c
core/al/al_pnp.h
core/al/kernel/al_ci_ca.c
core/al/kernel/al_pnp.c
inc/iba/ib_al.h

index a75e59b..8d65414 100644 (file)
@@ -57,7 +57,8 @@ ib_api_status_t
 create_ci_ca(\r
        IN                              al_obj_t                                        *p_parent_obj,\r
        IN              const   ci_interface_t*                         p_ci,\r
-       IN              const   PDEVICE_OBJECT                          p_hca_dev\r
+       IN              const   PDEVICE_OBJECT                          p_hca_dev,\r
+       IN              const   PDEVICE_OBJECT                          p_fdo\r
        );\r
 \r
 DEVICE_OBJECT*\r
@@ -65,6 +66,11 @@ get_ca_dev(
        IN              const   ib_ca_handle_t                          h_ca );\r
 #endif\r
 \r
+#define MAX_AE                         32\r
+typedef struct _al_ae_info {\r
+       ib_pnp_event_t                  pnp_event;\r
+       uint8_t                                 port_index;\r
+} al_ae_info_t;\r
 \r
 \r
 typedef struct _al_ci_ca\r
@@ -106,6 +112,12 @@ typedef struct _al_ci_ca
        /* "end of PnP handling" event */\r
        cl_event_t                                      event;\r
 \r
+       /* Array of pending AEs (Asynchronic events) */\r
+       al_ae_info_t                            ae[MAX_AE];     /* pending Asynchronic Events */                \r
+       int                                             ci;                     /* Consumer Index - first event to handle */\r
+       int                                             pi;                     /* Producer index - next not handled event */\r
+       int                                                     cnt;            /* number of not handled events */\r
+\r
 }      al_ci_ca_t;\r
 \r
 \r
index 6271c4b..ae992d7 100644 (file)
@@ -250,6 +250,7 @@ ci_ca_async_event(
        p_event_item = PARENT_STRUCT( p_item, event_item_t, async_item.pool_item );\r
        p_event_item->event_rec.code = p_event_rec->code;\r
        p_event_item->event_rec.context = p_event_rec->context;\r
+       p_event_item->event_rec.port_number = p_event_rec->port_number;\r
 \r
        /* Queue the item on the asynchronous callback thread for processing. */\r
        p_event_item->async_item.pfn_callback = ci_ca_process_event_cb;\r
@@ -300,10 +301,27 @@ ci_ca_process_event_cb(
                cq_async_event_cb( &p_event_item->event_rec );\r
                break;\r
 \r
+#ifdef CL_KERNEL\r
+\r
+       case IB_AE_LID_CHANGE:\r
+       case IB_AE_CLIENT_REREGISTER:\r
+               // These AE events will be generated even in the case when\r
+               // SM was restaretd but LID will not actually change.\r
+               // It's important to propagate these event (via PnP mechanism)\r
+               // up to subscribers. Otherwise, there will be no ping after\r
+               // subnet manager restart\r
+               //if (AL_OBJ_IS_TYPE(p_obj, AL_OBJ_TYPE_CI_CA)\r
+               if (AL_BASE_TYPE( p_obj->type) == AL_OBJ_TYPE_CI_CA) {\r
+                               pnp_force_event( (struct _al_ci_ca *) p_obj, IB_PNP_LID_CHANGE,\r
+                                       p_event_item->event_rec.port_number );\r
+               }\r
+               break;\r
+#endif //CL_KERNEL\r
+\r
        case IB_AE_PORT_TRAP:\r
        case IB_AE_PORT_DOWN:\r
        case IB_AE_PORT_ACTIVE:\r
-       case IB_AE_CLIENT_REREGISTER:\r
+       \r
 #ifdef CL_KERNEL\r
                /* The SMI polling routine may report a PnP event. */\r
                force_smi_poll();\r
index 3992b43..fdd6c85 100644 (file)
@@ -216,6 +216,13 @@ al_reg_pnp(
        IN                              KEVENT                                          *p_sync_event,\r
                OUT                     ib_pnp_handle_t* const          ph_pnp );\r
 \r
+void\r
+pnp_force_event(\r
+       IN              struct _al_ci_ca         * p_ci_ca,\r
+       IN              ib_pnp_event_t pnp_event,\r
+       IN              uint8_t port_num);\r
+\r
+\r
 #endif /* CL_KERNEL */\r
 \r
 static inline ib_pnp_class_t\r
index 979c9ec..b24f583 100644 (file)
@@ -354,6 +354,7 @@ ci_ca_async_event_cb(
        event_rec.code = p_event_record->type;\r
        event_rec.context = p_event_record->context;\r
        event_rec.vendor_specific = p_event_record->vendor_specific;\r
+       event_rec.port_number = p_event_record->port_number;\r
 \r
        ci_ca_async_event( &event_rec );\r
 \r
index 0c34647..c3026f2 100644 (file)
@@ -605,6 +605,7 @@ pnp_create_context(
        {\r
                AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_PNP,\r
                        ("p_context is already in context map %I64x \n",p_context->guid));\r
+               cl_free( p_context );\r
                p_context = NULL;\r
        }\r
        \r
@@ -1490,6 +1491,38 @@ __pnp_check_ports(
                        __pnp_process_port_forward( &event_rec );\r
                }\r
        }\r
+\r
+       /* send asynchronous events */\r
+       {\r
+               int ci, cnt, i;\r
+               al_ae_info_t ae[MAX_AE]; /* pending Asynchronic Events */               \r
+\r
+               if (!p_ci_ca->cnt)\r
+                       return;\r
+               \r
+               /* copy events in temp array */\r
+               ci_ca_lock_attr( p_ci_ca );\r
+               cnt = p_ci_ca->cnt;\r
+               ci = p_ci_ca->ci;\r
+               for (i=0; i<cnt; ++i)\r
+               {\r
+                       ae[i] = p_ci_ca->ae[ci];\r
+                       if ( ++ci >= MAX_AE )\r
+                               ci = 0;\r
+               }\r
+               cnt = p_ci_ca->cnt;\r
+               p_ci_ca->cnt = 0;\r
+               p_ci_ca->ci = ci;\r
+               ci_ca_unlock_attr( p_ci_ca );\r
+\r
+               for (i=0; i<cnt; ++i)\r
+               {\r
+                       event_rec.pnp_event = ae[i].pnp_event;\r
+                       event_rec.port_index = ae[i].port_index;\r
+                       __pnp_process_port_forward( &event_rec );\r
+               }\r
+       } \r
+\r
 }\r
 \r
 \r
@@ -1749,3 +1782,32 @@ ib_reject_ioc(
        AL_EXIT( AL_DBG_PNP );\r
        return IB_UNSUPPORTED;\r
 }\r
+\r
+void\r
+pnp_force_event(\r
+       IN              struct _al_ci_ca         * p_ci_ca,\r
+       IN              ib_pnp_event_t pnp_event,\r
+       IN              uint8_t port_num)\r
+{\r
+#define PORT_INDEX_OFFSET 1\r
+\r
+       ASSERT(p_ci_ca);\r
+       \r
+       if (!p_ci_ca)\r
+               return;\r
+       \r
+       p_ci_ca->ae[p_ci_ca->pi].pnp_event = pnp_event;\r
+       p_ci_ca->ae[p_ci_ca->pi].port_index = port_num - PORT_INDEX_OFFSET;\r
+       ci_ca_lock_attr( p_ci_ca );\r
+       if ( ++p_ci_ca->pi >= MAX_AE )\r
+               p_ci_ca->pi = 0;\r
+       ASSERT(p_ci_ca->cnt < MAX_AE);\r
+       if ( ++p_ci_ca->cnt > MAX_AE )\r
+       {\r
+               p_ci_ca->cnt = MAX_AE;\r
+               p_ci_ca->ci =p_ci_ca->pi;\r
+       }\r
+       ci_ca_unlock_attr( p_ci_ca );\r
+}\r
+\r
+\r
index 72a8b4f..ba30e9b 100644 (file)
@@ -473,6 +473,8 @@ typedef struct _ib_async_event_rec
                TO_LONG_PTR(struct _ib_srq*,                    h_srq);\r
 \r
        } handle;\r
+       \r
+       uint8_t                                                                         port_number;\r
 \r
 }      ib_async_event_rec_t;\r
 /*\r