[IBAL] Limit time spent at DISPATCH_LEVEL when processing MADs.
authorleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sun, 13 Jul 2008 11:35:53 +0000 (11:35 +0000)
committerleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sun, 13 Jul 2008 11:35:53 +0000 (11:35 +0000)
In working with some switch SMs, I found that under stress the QP0 MAD processing could get delayed by eternal QP1 MAD processing (from hitting the SA for path queries).  This caused the SMs to remove the node from the fabric (multicast group membership, etc) because it appeared unreachable.

This patch adds a DPC for QP0 and QP1 to the SMI, and limits the SMI to processing 16 MADs before re-queueing the DPC to the DPC queue.

Because QP0 processing is crucial to the fabric operating properly, the QP0 DPC is set to high importance so that it always gets queued to the front of the DPC queue, pre-empting any QP1 processing (among other things).

In any case, with this patch all my changes have now been mailed to the list.

Signed-off-by: Fab Tillier <ftillier@microsoft.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1393 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

core/al/kernel/al_smi.c
core/al/kernel/al_smi.h

index b3cc398..255c0c2 100644 (file)
@@ -140,6 +140,22 @@ spl_qp_send_comp_cb(
        IN              const   ib_cq_handle_t                          h_cq,\r
        IN                              void                                            *cq_context );\r
 \r
+void\r
+spl_qp_send_dpc_cb(\r
+    IN              KDPC                        *p_dpc,\r
+    IN              void                        *context,\r
+    IN              void                        *arg1,\r
+    IN              void                        *arg2\r
+    );\r
+\r
+void\r
+spl_qp_recv_dpc_cb(\r
+    IN              KDPC                        *p_dpc,\r
+    IN              void                        *context,\r
+    IN              void                        *arg1,\r
+    IN              void                        *arg2\r
+    );\r
+\r
 void\r
 spl_qp_recv_comp_cb(\r
        IN              const   ib_cq_handle_t                          h_cq,\r
@@ -554,7 +570,17 @@ create_spl_qp_svc(
        cl_qlist_init( &p_spl_qp_svc->send_queue );\r
        cl_qlist_init( &p_spl_qp_svc->recv_queue );\r
        cl_spinlock_init(&p_spl_qp_svc->cache_lock);\r
-       \r
+\r
+    /* Initialize the DPCs. */\r
+    KeInitializeDpc( &p_spl_qp_svc->send_dpc, spl_qp_send_dpc_cb, p_spl_qp_svc );\r
+    KeInitializeDpc( &p_spl_qp_svc->recv_dpc, spl_qp_recv_dpc_cb, p_spl_qp_svc );\r
+\r
+    if( qp_type == IB_QPT_QP0 )\r
+    {\r
+        KeSetImportanceDpc( &p_spl_qp_svc->send_dpc, HighImportance );\r
+        KeSetImportanceDpc( &p_spl_qp_svc->recv_dpc, HighImportance );\r
+    }\r
+\r
 #if defined( CL_USE_MUTEX )\r
        /* Initialize async callbacks and flags for send/receive processing. */\r
        p_spl_qp_svc->send_async_queued = FALSE;\r
@@ -2461,6 +2487,8 @@ spl_qp_send_comp_cb(
 \r
        AL_ENTER( AL_DBG_SMI );\r
 \r
+       UNREFERENCED_PARAMETER( h_cq );\r
+\r
        CL_ASSERT( cq_context );\r
        p_spl_qp_svc = cq_context;\r
 \r
@@ -2477,21 +2505,55 @@ spl_qp_send_comp_cb(
        cl_spinlock_release( &p_spl_qp_svc->obj.lock );\r
 \r
 #else\r
+    cl_spinlock_acquire( &p_spl_qp_svc->obj.lock );\r
+       if( p_spl_qp_svc->state != SPL_QP_ACTIVE )\r
+       {\r
+               cl_spinlock_release( &p_spl_qp_svc->obj.lock );\r
+        AL_EXIT( AL_DBG_SMI );\r
+               return;\r
+       }\r
+       cl_atomic_inc( &p_spl_qp_svc->in_use_cnt );\r
+       cl_spinlock_release( &p_spl_qp_svc->obj.lock );\r
 \r
-       /* Invoke the callback directly. */\r
+    /* Queue the DPC. */\r
        CL_ASSERT( h_cq == p_spl_qp_svc->h_send_cq );\r
-       spl_qp_comp( p_spl_qp_svc, h_cq, IB_WC_SEND );\r
+    KeInsertQueueDpc( &p_spl_qp_svc->send_dpc, NULL, NULL );\r
+#endif\r
+\r
+       AL_EXIT( AL_DBG_SMI );\r
+}\r
+\r
+\r
+void\r
+spl_qp_send_dpc_cb(\r
+    IN              KDPC                        *p_dpc,\r
+    IN              void                        *context,\r
+    IN              void                        *arg1,\r
+    IN              void                        *arg2\r
+    )\r
+{\r
+       spl_qp_svc_t*                   p_spl_qp_svc;\r
+\r
+       AL_ENTER( AL_DBG_SMI );\r
+\r
+       CL_ASSERT( context );\r
+       p_spl_qp_svc = context;\r
+\r
+    UNREFERENCED_PARAMETER( p_dpc );\r
+    UNREFERENCED_PARAMETER( arg1 );\r
+    UNREFERENCED_PARAMETER( arg2 );\r
+\r
+       spl_qp_comp( p_spl_qp_svc, p_spl_qp_svc->h_send_cq, IB_WC_SEND );\r
 \r
        /* Continue processing any queued MADs on the QP. */\r
        special_qp_resume_sends( p_spl_qp_svc->h_qp );\r
 \r
-#endif\r
+    cl_atomic_dec( &p_spl_qp_svc->in_use_cnt );\r
 \r
-       AL_EXIT( AL_DBG_SMI );\r
+    AL_EXIT( AL_DBG_SMI );\r
 }\r
 \r
 \r
-\r
 #if defined( CL_USE_MUTEX )\r
 void\r
 spl_qp_send_async_cb(\r
@@ -2536,6 +2598,8 @@ spl_qp_recv_comp_cb(
 \r
        AL_ENTER( AL_DBG_SMI );\r
 \r
+       UNREFERENCED_PARAMETER( h_cq );\r
+\r
        CL_ASSERT( cq_context );\r
        p_spl_qp_svc = cq_context;\r
 \r
@@ -2552,16 +2616,51 @@ spl_qp_recv_comp_cb(
        cl_spinlock_release( &p_spl_qp_svc->obj.lock );\r
 \r
 #else\r
+    cl_spinlock_acquire( &p_spl_qp_svc->obj.lock );\r
+       if( p_spl_qp_svc->state != SPL_QP_ACTIVE )\r
+       {\r
+               cl_spinlock_release( &p_spl_qp_svc->obj.lock );\r
+        AL_EXIT( AL_DBG_SMI );\r
+               return;\r
+       }\r
+       cl_atomic_inc( &p_spl_qp_svc->in_use_cnt );\r
+       cl_spinlock_release( &p_spl_qp_svc->obj.lock );\r
 \r
+    /* Queue the DPC. */\r
        CL_ASSERT( h_cq == p_spl_qp_svc->h_recv_cq );\r
-       spl_qp_comp( p_spl_qp_svc, h_cq, IB_WC_RECV );\r
-\r
+    KeInsertQueueDpc( &p_spl_qp_svc->recv_dpc, NULL, NULL );\r
 #endif\r
 \r
        AL_EXIT( AL_DBG_SMI );\r
 }\r
 \r
 \r
+void\r
+spl_qp_recv_dpc_cb(\r
+    IN              KDPC                        *p_dpc,\r
+    IN              void                        *context,\r
+    IN              void                        *arg1,\r
+    IN              void                        *arg2\r
+    )\r
+{\r
+       spl_qp_svc_t*                   p_spl_qp_svc;\r
+\r
+       AL_ENTER( AL_DBG_SMI );\r
+\r
+       CL_ASSERT( context );\r
+       p_spl_qp_svc = context;\r
+\r
+    UNREFERENCED_PARAMETER( p_dpc );\r
+    UNREFERENCED_PARAMETER( arg1 );\r
+    UNREFERENCED_PARAMETER( arg2 );\r
+\r
+       spl_qp_comp( p_spl_qp_svc, p_spl_qp_svc->h_recv_cq, IB_WC_RECV );\r
+\r
+    cl_atomic_dec( &p_spl_qp_svc->in_use_cnt );\r
+\r
+    AL_EXIT( AL_DBG_SMI );\r
+}\r
+\r
 \r
 #if defined( CL_USE_MUTEX )\r
 void\r
@@ -2589,7 +2688,7 @@ spl_qp_recv_async_cb(
 #endif\r
 \r
 \r
-\r
+#define SPL_QP_MAX_POLL 16\r
 /*\r
  * Special QP completion handler.\r
  */\r
@@ -2607,6 +2706,7 @@ spl_qp_comp(
        ib_mad_element_t*               p_mad_element;\r
        ib_smp_t*                               p_smp;\r
        ib_api_status_t                 status;\r
+    int                     max_poll = SPL_QP_MAX_POLL;\r
 \r
        AL_ENTER( AL_DBG_SMI_CB );\r
 \r
@@ -2625,7 +2725,7 @@ spl_qp_comp(
 \r
        wc.p_next = NULL;\r
        /* Process work completions. */\r
-       while( ib_poll_cq( h_cq, &p_free_wc, &p_done_wc ) == IB_SUCCESS )\r
+       while( max_poll && ib_poll_cq( h_cq, &p_free_wc, &p_done_wc ) == IB_SUCCESS )\r
        {\r
                /* Process completions one at a time. */\r
                CL_ASSERT( p_done_wc );\r
@@ -2713,13 +2813,25 @@ spl_qp_comp(
                        spl_qp_svc_reset( p_spl_qp_svc );\r
                }\r
                p_free_wc = &wc;\r
-       }\r
-\r
-       /* Rearm the CQ. */\r
-       status = ib_rearm_cq( h_cq, FALSE );\r
-       CL_ASSERT( status == IB_SUCCESS );\r
-\r
-       cl_atomic_dec( &p_spl_qp_svc->in_use_cnt );\r
+        --max_poll;\r
+       }\r
+\r
+    if( max_poll == 0 )\r
+    {\r
+        /* We already have an in_use_cnt reference - use it to queue the DPC. */\r
+        if( wc_type == IB_WC_SEND )\r
+            KeInsertQueueDpc( &p_spl_qp_svc->send_dpc, NULL, NULL );\r
+        else\r
+            KeInsertQueueDpc( &p_spl_qp_svc->recv_dpc, NULL, NULL );\r
+    }\r
+    else\r
+    {\r
+           /* Rearm the CQ. */\r
+           status = ib_rearm_cq( h_cq, FALSE );\r
+           CL_ASSERT( status == IB_SUCCESS );\r
+\r
+           cl_atomic_dec( &p_spl_qp_svc->in_use_cnt );\r
+    }\r
        AL_EXIT( AL_DBG_SMI_CB );\r
 }\r
 \r
index 95b2718..62cb0fe 100644 (file)
@@ -157,6 +157,9 @@ typedef struct _spl_qp_svc
        ib_pool_key_t                           pool_key;\r
        ib_mad_svc_handle_t                     h_mad_svc;\r
 \r
+    KDPC                        send_dpc;\r
+    KDPC                        recv_dpc;\r
+\r
 }      spl_qp_svc_t;\r
 \r
 \r