]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
[ipoib] ipoib - recv processing takes too much time in DPC
authorTzachi Dar <tzachid@mellanox.co.il>
Mon, 30 Aug 2010 12:30:19 +0000 (12:30 +0000)
committerTzachi Dar <tzachid@mellanox.co.il>
Mon, 30 Aug 2010 12:30:19 +0000 (12:30 +0000)
When processing of receive packet, the function stays in DPC too much time. In win2008 the OS throws an assert warning that too much time is spent in DPC and it may affect the system.

The fix is to move the receive processing to a workitem. The IPOIB give-up after some time and return to process receive packet in workitem. that allows other DPCs and workitems too run in parallel.

commit 6315 in svn://mtls50/svn.wininf/branches/MLNX_WinOF-2_1_2

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

trunk/ulp/ipoib/kernel/ipoib_adapter.c
trunk/ulp/ipoib/kernel/ipoib_adapter.h
trunk/ulp/ipoib/kernel/ipoib_port.c
trunk/ulp/ipoib/kernel/ipoib_port.h
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.cpp
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.h
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.h

index 003ba1231d7749c69e94bd096a5afc37cf40dbbe..06433a6db83c564b06a17355ac91f6783cd4bcc2 100644 (file)
@@ -224,6 +224,9 @@ ipoib_create_adapter(
                }\r
        }\r
 \r
+       NdisMGetDeviceProperty(h_adapter, &p_adapter->pdo, NULL, NULL, NULL, NULL);\r
+       ASSERT(p_adapter->pdo != NULL);\r
+\r
        p_adapter->p_stat = ipoib_st_dev_add();\r
        if ( p_adapter->p_stat ) \r
                p_adapter->p_stat->p_adapter = p_adapter;\r
index 492863ee4da3bdb37c74b3d335ce4094bd5e628d..03650035c08a480bc4b016392703cfbdcff17a0c 100644 (file)
@@ -150,6 +150,7 @@ typedef struct _ipoib_adapter
 {\r
        cl_obj_t                                obj;\r
        NDIS_HANDLE                             h_adapter;\r
+       PDEVICE_OBJECT                  pdo;\r
        ipoib_ifc_data_t                guids;\r
 \r
        cl_list_item_t                  entry;\r
index 3953126e94798e6353e16883b067a08a3bd3105a..4a8290bfbbdb08bea3f9cb491ee2a89ef7f82c3b 100644 (file)
@@ -72,9 +72,6 @@ static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1,
 static void __port_do_mcast_garbage(ipoib_port_t* const        p_port );\r
 \r
 \r
-static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
-\r
-\r
 /******************************************************************************\r
 *\r
 * Declarations\r
@@ -605,6 +602,8 @@ __port_construct(
 \r
        __endpt_mgr_construct( p_port );\r
 \r
+       p_port->pPoWorkItem = NULL;\r
+\r
        KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE );\r
        KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE );\r
        \r
@@ -626,6 +625,12 @@ __port_init(
        p_port->port_num = p_pnp_rec->p_port_attr->port_num;\r
        p_port->p_adapter = p_adapter;\r
 \r
+       p_port->pPoWorkItem = IoAllocateWorkItem(p_adapter->pdo);\r
+       if( p_port->pPoWorkItem == NULL ) {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("IoAllocateWorkItem returned NULL\n") );\r
+               return IB_ERROR;\r
+       }\r
+       \r
        cl_status = cl_spinlock_init( &p_port->send_lock );\r
        if( cl_status != CL_SUCCESS )\r
        {\r
@@ -682,9 +687,6 @@ __port_init(
                return status;\r
        }\r
 \r
-        KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port);\r
-\r
-\r
         /* Initialize multicast garbage collector timer and DPC object */\r
         KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port);\r
         KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);\r
@@ -795,6 +797,7 @@ __port_free(
 \r
        cl_obj_deinit( p_obj );\r
 \r
+       IoFreeWorkItem( p_port->pPoWorkItem );\r
        cl_free( p_port );\r
 \r
        IPOIB_EXIT( IPOIB_DBG_INIT );\r
@@ -1611,27 +1614,49 @@ ipoib_return_packet(
        IPOIB_EXIT( IPOIB_DBG_RECV );\r
 }\r
 \r
-static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2)\r
-{\r
+static BOOLEAN\r
+__recv_cb_internal(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context,\r
+       IN                              uint32_t                                         *p_recv_cnt\r
+       );\r
 \r
-       ipoib_port_t *p_port = context;\r
 \r
-       UNREFERENCED_PARAMETER(p_gc_dpc);\r
-       UNREFERENCED_PARAMETER(s_arg1);\r
-       UNREFERENCED_PARAMETER(s_arg2);\r
+static void\r
+__iopoib_WorkItem(\r
+       IN                              DEVICE_OBJECT*                          p_dev_obj,\r
+       IN                              void*                                           context )\r
+{\r
 \r
+       ipoib_port_t *p_port = ( ipoib_port_t* ) context;\r
+       BOOLEAN WorkToDo = TRUE;\r
+       KIRQL irql;\r
+       uint32_t recv_cnt = 0;\r
+       uint32_t total_recv_cnt = 0;\r
 \r
-       __recv_cb(NULL, p_port);\r
-       ipoib_port_deref( p_port, ref_recv_cb );\r
+       UNREFERENCED_PARAMETER(p_dev_obj);\r
 \r
+       while (WorkToDo && total_recv_cnt < 512) {\r
+               irql = KeRaiseIrqlToDpcLevel();\r
+               WorkToDo = __recv_cb_internal(NULL, p_port, &recv_cnt);\r
+               KeLowerIrql(irql);\r
+               total_recv_cnt += recv_cnt;\r
+       }\r
 \r
+       if (WorkToDo) {\r
+               IoQueueWorkItem( p_port->pPoWorkItem, __iopoib_WorkItem, DelayedWorkQueue, p_port);\r
+       } else {\r
+               // Release the reference count that was incremented when queued the work item.\r
+               ipoib_port_deref( p_port, ref_recv_cb );\r
+       }\r
 }\r
 \r
 \r
-static void\r
-__recv_cb(\r
+static BOOLEAN\r
+__recv_cb_internal(\r
        IN              const   ib_cq_handle_t                          h_cq,\r
-       IN                              void                                            *cq_context )\r
+       IN                              void                                            *cq_context,\r
+       IN                              uint32_t*                                        p_recv_cnt)\r
 {\r
        ipoib_port_t            *p_port;\r
        ib_api_status_t         status;\r
@@ -1639,6 +1664,8 @@ __recv_cb(
        int32_t                         pkt_cnt, recv_cnt = 0, shortage, discarded;\r
        cl_qlist_t                      done_list, bad_list;\r
        size_t                          i;\r
+       BOOLEAN                         WorkToDo = FALSE;\r
+       \r
        PERF_DECLARE( RecvCompBundle );\r
        PERF_DECLARE( RecvCb );\r
        PERF_DECLARE( PollRecv );\r
@@ -1655,8 +1682,6 @@ __recv_cb(
 \r
        cl_perf_start( RecvCb );\r
 \r
-       UNUSED_PARAM( h_cq );\r
-\r
        p_port = (ipoib_port_t*)cq_context;\r
 \r
        cl_qlist_init( &done_list );\r
@@ -1693,6 +1718,8 @@ __recv_cb(
 \r
        } while( (!p_free) && (recv_cnt < 128));\r
 \r
+       *p_recv_cnt = (uint32_t)recv_cnt;\r
+\r
        /* We're done looking at the endpoint map, release the reference. */\r
        cl_atomic_dec( &p_port->endpt_rdr );\r
 \r
@@ -1776,21 +1803,39 @@ __recv_cb(
                 * and eliminate the possibility of having a call to\r
                 * __endpt_mgr_insert find a duplicate.\r
                 */\r
+               ASSERT(WorkToDo == FALSE);\r
                cl_perf_start( RearmRecv );\r
                status = p_port->p_adapter->p_ifc->rearm_cq(\r
                        p_port->ib_mgr.h_recv_cq, FALSE );\r
                cl_perf_stop( &p_port->p_adapter->perf, RearmRecv );\r
                CL_ASSERT( status == IB_SUCCESS );\r
 \r
-               ipoib_port_deref( p_port, ref_recv_cb );\r
        } else {\r
-               // Please note the reference is still up\r
-               KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL);\r
+               if (h_cq) {\r
+                       // increment reference to ensure no one release the object while work iteam is queued\r
+                       ipoib_port_ref( p_port, ref_recv_cb );\r
+                       IoQueueWorkItem( p_port->pPoWorkItem, __iopoib_WorkItem, DelayedWorkQueue, p_port);\r
+                       WorkToDo = FALSE;\r
+               } else {\r
+                       WorkToDo = TRUE;\r
+               }\r
        }\r
-\r
+       ipoib_port_deref( p_port, ref_recv_cb );\r
        cl_perf_stop( &p_port->p_adapter->perf, RecvCb );\r
 \r
        IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return WorkToDo;\r
+}\r
+\r
+\r
+static void\r
+__recv_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context )\r
+{\r
+       uint32_t recv_cnt;\r
+       \r
+       __recv_cb_internal(h_cq, cq_context, &recv_cnt);\r
 }\r
 \r
 \r
index 955a5d8ad22d613757f3af471d72de79838332fa..c3dcac1b015005c0a1a2ce415264f700818133ce 100644 (file)
@@ -502,8 +502,6 @@ typedef struct _ipoib_port
        ipoib_recv_mgr_t                recv_mgr;\r
        ipoib_send_mgr_t                send_mgr;\r
 \r
-       KDPC                                    recv_dpc;\r
-\r
        ipoib_endpt_mgr_t               endpt_mgr;\r
 \r
        ipoib_endpt_t                   *p_local_endpt;\r
@@ -520,6 +518,7 @@ typedef struct _ipoib_port
        KTIMER                                  gc_timer;\r
        uint32_t                                bc_join_retry_cnt;\r
        ib_net16_t                              base_lid;\r
+       PIO_WORKITEM                    pPoWorkItem;\r
        ipoib_hdr_t                             hdr[1]; /* Must be last! */\r
 \r
 }      ipoib_port_t;\r
index 01a6898b7e132b6e99e88ce8daa339d9f5476063..322b59615398b70435fbddf5b79ef94810866a73 100644 (file)
@@ -214,6 +214,9 @@ ipoib_create_adapter(
                }\r
        }\r
 \r
+       NdisMGetDeviceProperty(h_adapter, &p_adapter->pdo, NULL, NULL, NULL, NULL);\r
+       ASSERT(p_adapter->pdo != NULL);\r
+\r
        p_adapter->p_stat = ipoib_st_dev_add();\r
        if ( p_adapter->p_stat ) \r
                p_adapter->p_stat->p_adapter = p_adapter;\r
index 12027d63554fa9d7db7179d4dd24db495b6cdf89..2092ba8ceabb8b04a310573959049ff205b4d177 100644 (file)
@@ -185,6 +185,7 @@ typedef struct _ipoib_adapter
 {\r
        cl_obj_t                                obj;\r
        NDIS_HANDLE                             h_adapter;\r
+       PDEVICE_OBJECT                  pdo;\r
        ipoib_ifc_data_t                guids;\r
 \r
        cl_list_item_t                  entry;\r
index da48cd01f82fc7232bf14c4c4cc31b7182953844..5d42fefde64ce4a0721315b3ae9bf711d040cf55 100644 (file)
@@ -76,9 +76,6 @@ ipoib_port_t  *gp_ipoib_port;
 static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
 static void __port_do_mcast_garbage(ipoib_port_t* const        p_port );\r
 \r
-\r
-static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
-\r
 #if 0\r
 #ifndef _IPOIB_DEBUG_NDIS6\r
 #define _IPOIB_DEBUG_NDIS6\r
@@ -701,6 +698,8 @@ __port_construct(
 \r
        __endpt_mgr_construct( p_port );\r
 \r
+       p_port->pPoWorkItem = NULL;\r
+\r
        KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE );\r
        KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE );\r
        \r
@@ -722,6 +721,13 @@ __port_init(
        p_port->port_num = p_pnp_rec->p_port_attr->port_num;\r
        p_port->p_adapter = p_adapter;\r
 \r
+       p_port->pPoWorkItem = IoAllocateWorkItem(p_adapter->pdo);\r
+       if( p_port->pPoWorkItem == NULL )       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("IoAllocateWorkItem returned NULL\n") );\r
+               return IB_ERROR;\r
+       }\r
+\r
        cl_status = cl_spinlock_init( &p_port->send_lock );\r
        if( cl_status != CL_SUCCESS )\r
        {\r
@@ -787,9 +793,6 @@ __port_init(
                return status;\r
        }\r
 \r
-       KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port);\r
-\r
-\r
         /* Initialize multicast garbage collector timer and DPC object */\r
        KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port);\r
        KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);\r
@@ -928,6 +931,8 @@ __port_free(
        {\r
                cl_free ( p_port->p_ca_attrs );\r
        }\r
+\r
+       IoFreeWorkItem( p_port->pPoWorkItem );\r
        cl_free( p_port );\r
 \r
        IPOIB_EXIT( IPOIB_DBG_INIT );\r
@@ -1969,24 +1974,49 @@ ipoib_return_net_buffer_list(
        IPOIB_EXIT( IPOIB_DBG_RECV );\r
 }\r
 \r
-static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2)\r
+static BOOLEAN\r
+__recv_cb_internal(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context,\r
+       IN                              uint32_t                                         *p_recv_cnt\r
+       );\r
+\r
+\r
+static void\r
+__iopoib_WorkItem(\r
+       IN                              DEVICE_OBJECT*                          p_dev_obj,\r
+       IN                              void*                                           context )\r
 {\r
 \r
-       ipoib_port_t *p_port = (ipoib_port_t *) context;\r
+       ipoib_port_t *p_port = ( ipoib_port_t* ) context;\r
+       BOOLEAN WorkToDo = TRUE;\r
+       KIRQL irql;\r
+       uint32_t recv_cnt = 0;\r
+       uint32_t total_recv_cnt = 0;\r
 \r
-       UNREFERENCED_PARAMETER(p_gc_dpc);\r
-       UNREFERENCED_PARAMETER(s_arg1);\r
-       UNREFERENCED_PARAMETER(s_arg2);\r
+       UNREFERENCED_PARAMETER(p_dev_obj);\r
 \r
-       __recv_cb(NULL, p_port);\r
-       ipoib_port_deref( p_port, ref_recv_cb );\r
+       while (WorkToDo && total_recv_cnt < 512) {\r
+               irql = KeRaiseIrqlToDpcLevel();\r
+               WorkToDo = __recv_cb_internal(NULL, p_port, &recv_cnt);\r
+               KeLowerIrql(irql);\r
+               total_recv_cnt += recv_cnt;\r
+       }\r
+\r
+       if (WorkToDo) {\r
+               IoQueueWorkItem( p_port->pPoWorkItem, __iopoib_WorkItem, DelayedWorkQueue, p_port);\r
+       } else {\r
+               // Release the reference count that was incremented when queued the work item.\r
+               ipoib_port_deref( p_port, ref_recv_cb );\r
+       }\r
 }\r
 \r
 \r
-static void\r
-__recv_cb(\r
+static BOOLEAN\r
+__recv_cb_internal(\r
        IN              const   ib_cq_handle_t                          h_cq,\r
-       IN                              void                                            *cq_context )\r
+       IN                              void                                            *cq_context,\r
+       IN                              uint32_t*                                        p_recv_cnt)\r
 {\r
        ipoib_port_t            *p_port;\r
        ib_api_status_t         status;\r
@@ -1995,6 +2025,7 @@ __recv_cb(
        cl_qlist_t                      done_list, bad_list;\r
        ULONG                           recv_complete_flags = 0;\r
        BOOLEAN                         res;\r
+       BOOLEAN                         WorkToDo = FALSE;\r
 \r
        PERF_DECLARE( RecvCompBundle );\r
        PERF_DECLARE( RecvCb );\r
@@ -2052,7 +2083,9 @@ __recv_cb(
                recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list );\r
                cl_perf_stop( &p_port->p_adapter->perf, FilterRecv );\r
 \r
-       } while( ( !p_free ) && ( recv_cnt < 16 )); //TODO restore back to 128\r
+       } while( ( !p_free ) && ( recv_cnt < 128 )); \r
+\r
+       *p_recv_cnt = (uint32_t)recv_cnt;\r
 \r
        /* We're done looking at the endpoint map, release the reference. */\r
        cl_atomic_dec( &p_port->endpt_rdr );\r
@@ -2180,6 +2213,7 @@ __recv_cb(
                 * and eliminate the possibility of having a call to\r
                 * __endpt_mgr_insert find a duplicate.\r
                 */\r
+               ASSERT(WorkToDo == FALSE);\r
                cl_perf_start( RearmRecv );\r
 \r
                status =\r
@@ -2188,14 +2222,32 @@ __recv_cb(
                cl_perf_stop( &p_port->p_adapter->perf, RearmRecv );\r
                CL_ASSERT( status == IB_SUCCESS );\r
 \r
-               ipoib_port_deref( p_port, ref_recv_cb );\r
        } else {\r
-               // Please note the reference is still up\r
-               KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL);\r
+               if (h_cq) {\r
+                       // increment reference to ensure no one release the object while work iteam is queued\r
+                       ipoib_port_ref( p_port, ref_recv_cb );\r
+                       IoQueueWorkItem( p_port->pPoWorkItem, __iopoib_WorkItem, DelayedWorkQueue, p_port);\r
+                       WorkToDo = FALSE;\r
+               } else {\r
+                       WorkToDo = TRUE;\r
+               }\r
        }\r
+       ipoib_port_deref( p_port, ref_recv_cb );\r
        cl_perf_stop( &p_port->p_adapter->perf, RecvCb );\r
 \r
        IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return WorkToDo;\r
+}\r
+       \r
+       \r
+static void\r
+__recv_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context )\r
+{\r
+       uint32_t recv_cnt;\r
+       \r
+       __recv_cb_internal(h_cq, cq_context, &recv_cnt);\r
 }\r
 \r
 \r
index fa1835c92de34053a0082170b9a0a81ad1a8bc5c..b646e06abd5ce26aca757509d0d4b9d6579fcff0 100644 (file)
@@ -606,8 +606,6 @@ typedef struct _ipoib_port
        ipoib_send_mgr_t                send_mgr;\r
        ipoib_send_desc_t *             p_desc;\r
 \r
-       KDPC                                    recv_dpc;\r
-\r
        ipoib_endpt_mgr_t               endpt_mgr;\r
        endpt_buf_mgr_t                 cm_buf_mgr;\r
        endpt_recv_mgr_t                cm_recv_mgr;\r
@@ -627,6 +625,7 @@ typedef struct _ipoib_port
        uint32_t                                bc_join_retry_cnt;\r
        ib_net16_t                              base_lid;\r
        LONG                                    n_no_progress;\r
+       PIO_WORKITEM                    pPoWorkItem;\r
        ipoib_hdr_t                             hdr[1]; /* Must be last! */\r
 \r
 }      ipoib_port_t;\r