]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
[MLTHCA] added polling mode support.
authorleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sun, 18 Jan 2009 13:47:55 +0000 (13:47 +0000)
committerleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sun, 18 Jan 2009 13:47:55 +0000 (13:47 +0000)
This patch is a second part of a workaround, added in rev. 1800 for MLX4.
It adds polling mode support for MTHCA.
This is needed for example in the case, when interrupts stop to be conveyed to the driver for some HW problem.
(Xsigo saw such case).
This patch additionally "actualize" the workaround (by off-commenting #if WORKAROUND_POLL_EQ) to enable polling mode without re-building the drivers.

Signed-off-by: James Yang [jyang@xsigo.com]
git-svn-id: svn://openib.tc.cornell.edu/gen1@1841 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

trunk/hw/mlx4/kernel/bus/ib/main.c
trunk/hw/mlx4/kernel/bus/inc/ib_verbs_ex.h
trunk/hw/mlx4/kernel/bus/net/eq.c
trunk/hw/mlx4/kernel/bus/net/mlx4.h
trunk/hw/mlx4/kernel/hca/fw.c
trunk/hw/mlx4/kernel/inc/vc.h
trunk/hw/mthca/kernel/hca_driver.c
trunk/hw/mthca/kernel/hca_driver.h
trunk/hw/mthca/kernel/mthca_dev.h
trunk/hw/mthca/kernel/mthca_eq.c

index bc08c15227e6dcc8588f5994434dba5598cbb1f2..8eed20691e5c662304d19508a5bd643f41d4d72c 100644 (file)
@@ -38,7 +38,7 @@
 #include "ib_cache.h"
 #include "net\mlx4.h"
 
-#if    WORKAROUND_POLL_EQ
+#if    1//WORKAROUND_POLL_EQ
 void mlx4_poll_eq(struct ib_device *dev, BOOLEAN bStart);
 #endif
 
@@ -569,7 +569,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        ibdev->ib_dev.x.get_cached_pkey         = ib_get_cached_pkey;
        ibdev->ib_dev.x.register_ev_cb          = mlx4_reset_cb_register;
        ibdev->ib_dev.x.unregister_ev_cb        = mlx4_reset_cb_unregister;
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
        ibdev->ib_dev.x.poll_eq                         = mlx4_poll_eq;
 #endif
        if (mlx4_is_livefish(ibdev->dev))
index 18b78fa4d625b6586a35ad897028864c12ad32ac..6ad4ad7e0abe5b721029843e86e7260f8ce52160 100644 (file)
@@ -52,7 +52,7 @@ struct ib_device_ex
                u8 port_num, __be16 pkey, u16 *index);
        int (*register_ev_cb) (struct ib_event_handler *event_handler);
        int (*unregister_ev_cb) (struct ib_event_handler *event_handler);
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
        void (*poll_eq)(struct ib_device *device, BOOLEAN bStart);
 #endif
 };
index 7ca721fcbc5a643db69156cd5a79c4cd2537fad9..2864f0ec819e00fcbe254cce9c7e6bf677719c87 100644 (file)
@@ -255,7 +255,7 @@ static BOOLEAN mlx4_interrupt(
        return (BOOLEAN)work;
 }
 
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
 
 BOOLEAN
 IsrSynchronizeRoutine(
@@ -744,7 +744,7 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
                eq_set_ci(&priv->eq_table.eq[i], 1);
 
 
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
        { /* Create a thread for polling EQs in case of missing interrupts from the card  */
                NTSTATUS status;
                OBJECT_ATTRIBUTES       attr;
@@ -866,7 +866,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
        struct mlx4_priv *priv = mlx4_priv(dev);
        int i;
 
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
        /* stop the EQ polling thread */
        if (priv->eq_table.threadObject) { 
                #define WAIT_TIME_MS    3000
index 8139f8fd2dd23ae30e0997d47141c4f94291d636..bc3d055adbab1d44d5b8261fe03ea3b55f448ddf 100644 (file)
@@ -233,7 +233,7 @@ struct mlx4_eq_table {
        int                     have_irq;
        u8                      inta_pin;
        u8                                              max_extra_eqs;
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
        KEVENT          thread_start_event;
        KEVENT          thread_stop_event;
        BOOLEAN         bTerminated;
index 2c0df1f2b60a39d68cf741331af42d21a25b81fc..678bb5b67f300b94a49f8b827a92066c2ba90882 100644 (file)
@@ -405,7 +405,7 @@ fw_access_ctrl(
        UNREFERENCED_PARAMETER(num_handles);\r
 \r
     if(!p_umv_buf ) {\r
-#if WORKAROUND_POLL_EQ\r
+#if 1//WORKAROUND_POLL_EQ\r
                if ((p_ci_op->command == FW_POLL_EQ_START) || (p_ci_op->command == FW_POLL_EQ_STOP)){ // poll EQ (in case of missed interrupt) \r
                        mlnx_hca_t *p_hca = (mlnx_hca_t *)h_ca;\r
                        struct ib_device *p_ibdev = hca2ibdev(p_hca);\r
index 73f4dc749ed3ee87512787f97f34fa80bb6786cb..fdfe9a2aacf607fd7afc58ee64bd6edbda5489ec 100644 (file)
@@ -51,7 +51,7 @@ struct _map_crspace {
 #define FW_OPEN_IF             0xe7
 #define FW_CLOSE_IF            0x7e
 
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
 #define FW_POLL_EQ_START               0x0D
 #define FW_POLL_EQ_STOP                0x0E
 #endif
@@ -79,3 +79,4 @@ typedef struct {
 } uplink_info_t;
 
 
+
index d41a3254364784730d7b2e00b6e63d467f0831d7..a43877ff5734df4b4f3ef1bd702ec2dcfa0dbb46 100644 (file)
@@ -85,6 +85,7 @@ UNICODE_STRING                                g_param_path;
 char                   mlnx_uvp_lib_name[MAX_LIB_NAME] = {"mthcau"};\r
 \r
 void reregister_hca( hca_dev_ext_t *p_ext );\r
+void mlnx_poll_eq(struct ib_device *device, BOOLEAN bStart);\r
 \r
 \r
 NTSTATUS\r
@@ -671,7 +672,27 @@ fw_access_ctrl(
        UNREFERENCED_PARAMETER(num_handles);\r
 \r
        if( !p_umv_buf )\r
-               return IB_UNSUPPORTED;\r
+       {\r
+#if 1//WORKAROUND_POLL_EQ\r
+               if ((p_ci_op->command == FW_POLL_EQ_START) || (p_ci_op->command == FW_POLL_EQ_STOP))\r
+               { // poll EQ (in case of missed interrupt) \r
+                       struct ib_device *ib_dev;\r
+                       p_hob = (mlnx_hob_t *)h_ca;\r
+                       ib_dev = IBDEV_FROM_HOB( p_hob );\r
+\r
+                       if(p_ci_op->command == FW_POLL_EQ_START)\r
+                       {\r
+                               mlnx_poll_eq(ib_dev,1);\r
+                       }else\r
+                       {\r
+                               mlnx_poll_eq(ib_dev,0);\r
+                       }\r
+                       return IB_SUCCESS;\r
+               }\r
+               else\r
+#endif\r
+                       return IB_UNSUPPORTED;\r
+       }\r
 \r
        p_context = (struct ib_ucontext *)h_ca;\r
        p_hob = HOB_FROM_IBDEV( p_context->device );\r
index 4e8fc3b65d032ee25ce343e65639e318e8144abd..6fa4d43798567617a666f5aae673c4f09b4403b3 100644 (file)
@@ -214,6 +214,11 @@ Firmware Update definitions
 #define FW_OPEN_IF             0xe7\r
 #define FW_CLOSE_IF            0x7e\r
 \r
+#if 1//WORKAROUND_POLL_EQ\r
+#define FW_POLL_EQ_START               0x0D\r
+#define FW_POLL_EQ_STOP                0x0E\r
+#endif\r
+\r
 #define FW_SIGNATURE           (0x5a445a44)\r
 #define FW_SECT_SIZE           (0x10000)\r
 \r
index a3dd1774a2eb70105a8b71c422c77afc95df8fc8..41fae6fb2d620d5e16833c0f363c4a22391b82f6 100644 (file)
@@ -229,6 +229,12 @@ struct mthca_eq_table {
        int                have_irq;
        u8                 inta_pin;
        KLOCK_QUEUE_HANDLE  lockh;
+#if 1//WORKAROUND_POLL_EQ
+       KEVENT          thread_start_event;
+       KEVENT          thread_stop_event;
+       BOOLEAN         bTerminated;
+       PVOID           threadObject;
+#endif
 };
 
 struct mthca_cq_table {
index 111dea71d175572f31d8530331803876977c2808..a431ed098e7e8b49d0a43d73467079936c8d961e 100644 (file)
@@ -596,6 +596,101 @@ static irqreturn_t mthca_arbel_msi_x_interrupt(int irq, void *eq_ptr,
 }\r
 #endif\r
 \r
+#if 1//WORKAROUND_POLL_EQ\r
+\r
+BOOLEAN\r
+IsrSynchronizeRoutine(\r
+       IN PVOID  SynchronizeContext\r
+       )\r
+{\r
+       struct mthca_dev *dev = (struct mthca_dev *)SynchronizeContext;\r
+\r
+       //Is this always correct?\r
+       mthca_arbel_interrupt(dev->ext->int_obj,dev);\r
+    \r
+       return TRUE;\r
+}\r
+\r
+\r
+VOID eq_polling_thread(void *ctx) \r
+{\r
+#define POLLING_INTERVAL_MS    50\r
+       NTSTATUS status;\r
+       struct mthca_dev *dev = (struct mthca_dev *)ctx;\r
+       PVOID wait_objects[2];\r
+       LARGE_INTEGER  wait_time;\r
+\r
+       wait_objects[0] = &dev->eq_table.thread_stop_event;\r
+       wait_objects[1] = &dev->eq_table.thread_start_event;\r
+\r
+       for(;;){\r
+\r
+               /* before start polling */\r
+               DbgPrint("Before polling.\n");\r
+               for (;;) {\r
+                       status = KeWaitForMultipleObjects( 2, wait_objects, \r
+                                                                                          WaitAny, Executive, KernelMode, FALSE, NULL, NULL );\r
+\r
+                       if ( status == STATUS_WAIT_0 ){/* thread stopped */\r
+                               DbgPrint("Signaled to stop polling.\n");\r
+                               break;          \r
+                       }\r
+\r
+                       /* start polling */\r
+                       if ( status == STATUS_WAIT_1 ){\r
+                               DbgPrint("Signaled to start polling.\n");\r
+                               break;          \r
+                       }\r
+\r
+               }\r
+\r
+               if(dev->eq_table.bTerminated) break;\r
+               if ( status == STATUS_WAIT_0 ) continue;/* thread stopped, wait for start again */\r
+\r
+               /* polling */\r
+               DbgPrint("Start polling.\n");\r
+               wait_time.QuadPart = -(int64_t)(((uint64_t)POLLING_INTERVAL_MS) * 10000);\r
+               for (;;) {\r
+                       //mlx4_interrupt( NULL, &priv->dev );\r
+                       KeSynchronizeExecution(dev->ext->int_obj, IsrSynchronizeRoutine, dev);\r
+\r
+                       status = KeWaitForSingleObject( &dev->eq_table.thread_stop_event, \r
+                                                                                       Executive, KernelMode, FALSE, &wait_time );\r
+                       if ( status == STATUS_SUCCESS ) {\r
+                               //KeClearEvent(&priv->eq_table.thread_stop_event);\r
+                               DbgPrint("Signaled to stop polling while in polling mode.\n");\r
+                               break;          /* thread stopped */\r
+                       }\r
+               }\r
+\r
+               if(dev->eq_table.bTerminated) break;\r
+       }\r
+\r
+       DbgPrint("Polling thread terminated.\n");\r
+       PsTerminateSystemThread(STATUS_SUCCESS);\r
+\r
+}\r
+\r
+\r
+void mlnx_poll_eq(struct ib_device *device, BOOLEAN bStart)\r
+{\r
+       LONG signalled=0;\r
+       struct mthca_dev *dev = (struct mthca_dev *)(device);\r
+\r
+       if(bStart){\r
+               /* signal start of polling */\r
+               signalled = KeSetEvent(         \r
+                       &dev->eq_table.thread_start_event, IO_NO_INCREMENT, FALSE );\r
+       }else{\r
+               /* signal end of polling */\r
+               signalled = KeSetEvent(         \r
+                       &dev->eq_table.thread_stop_event, IO_NO_INCREMENT, FALSE );\r
+       }\r
+\r
+}\r
+\r
+#endif\r
+\r
 static int mthca_create_eq(struct mthca_dev *dev,\r
                                     int nent,\r
                                     u8 intr,\r
@@ -1061,6 +1156,39 @@ int mthca_init_eq_table(struct mthca_dev *dev)
                else\r
                        tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);\r
 \r
+#if 1//WORKAROUND_POLL_EQ\r
+       { /* Create a thread for polling EQs in case of missing interrupts from the card  */\r
+               NTSTATUS status;\r
+               OBJECT_ATTRIBUTES       attr;\r
+               HANDLE  handle;\r
+\r
+               KeInitializeEvent(&dev->eq_table.thread_start_event, SynchronizationEvent, FALSE);\r
+               KeInitializeEvent(&dev->eq_table.thread_stop_event, SynchronizationEvent, FALSE);\r
+               dev->eq_table.bTerminated = FALSE;\r
+               dev->eq_table.threadObject = NULL;\r
+               InitializeObjectAttributes( &attr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );\r
+               status = PsCreateSystemThread( &handle, \r
+                       THREAD_ALL_ACCESS, &attr, NULL, NULL, eq_polling_thread, dev );\r
+               if (NT_SUCCESS(status)) {\r
+                       status = ObReferenceObjectByHandle(\r
+                               handle,\r
+                               THREAD_ALL_ACCESS,\r
+                               NULL,\r
+                               KernelMode,\r
+                               &dev->eq_table.threadObject,\r
+                               NULL\r
+                               );\r
+\r
+                       ASSERT(status == STATUS_SUCCESS); //\r
+\r
+                       status = ZwClose(handle);\r
+\r
+                       ASSERT(NT_SUCCESS(status)); // Should always succeed\r
+\r
+               }\r
+       }\r
+#endif\r
+\r
        return 0;\r
 \r
 err_out_cmd:\r
@@ -1086,6 +1214,33 @@ void mthca_cleanup_eq_table(struct mthca_dev *dev)
        u8 status;\r
        int i;\r
 \r
+#if 1//WORKAROUND_POLL_EQ\r
+       /* stop the EQ polling thread */\r
+       if (dev->eq_table.threadObject) { \r
+               #define WAIT_TIME_MS    3000\r
+               NTSTATUS status;\r
+               LARGE_INTEGER  wait_time;\r
+               LONG signalled;\r
+\r
+               dev->eq_table.bTerminated = TRUE;\r
+\r
+               /* signal polling stopped in case it is not */\r
+               signalled = KeSetEvent(         \r
+                       &dev->eq_table.thread_stop_event, IO_NO_INCREMENT, FALSE );\r
+\r
+               /* wait for completion of the thread */\r
+               wait_time.QuadPart = -(int64_t)(((uint64_t)WAIT_TIME_MS) * 10000);\r
+               status = KeWaitForSingleObject( dev->eq_table.threadObject,\r
+                       Executive, KernelMode, FALSE, &wait_time );\r
+               ASSERT(status == STATUS_SUCCESS);\r
+\r
+               ObDereferenceObject(dev->eq_table.threadObject);\r
+\r
+               /* cleanup */\r
+               dev->eq_table.threadObject = NULL;\r
+       }\r
+#endif\r
+\r
        mthca_free_irqs(dev);\r
 \r
        mthca_MAP_EQ(dev, async_mask(dev),\r