[ofw][patch][MLX4, MTHCA] Add polling mode to MTHCA

Leonid Keller leonid at mellanox.co.il
Thu Jan 15 00:21:26 PST 2009


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 at xsigo.com]
 
 
Index: hw/mlx4/kernel/bus/ib/main.c
===================================================================
--- hw/mlx4/kernel/bus/ib/main.c (revision 1822)
+++ hw/mlx4/kernel/bus/ib/main.c (working copy)
@@ -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 @@
  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: hw/mlx4/kernel/bus/inc/ib_verbs_ex.h
===================================================================
--- hw/mlx4/kernel/bus/inc/ib_verbs_ex.h (revision 1822)
+++ hw/mlx4/kernel/bus/inc/ib_verbs_ex.h (working copy)
@@ -52,7 +52,7 @@
   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: hw/mlx4/kernel/bus/net/eq.c
===================================================================
--- hw/mlx4/kernel/bus/net/eq.c (revision 1822)
+++ hw/mlx4/kernel/bus/net/eq.c (working copy)
@@ -255,7 +255,7 @@
  return (BOOLEAN)work;
 }
 
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
 
 BOOLEAN
 IsrSynchronizeRoutine(
@@ -744,7 +744,7 @@
   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 @@
  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: hw/mlx4/kernel/bus/net/mlx4.h
===================================================================
--- hw/mlx4/kernel/bus/net/mlx4.h (revision 1822)
+++ hw/mlx4/kernel/bus/net/mlx4.h (working copy)
@@ -233,7 +233,7 @@
  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: hw/mlx4/kernel/hca/fw.c
===================================================================
--- hw/mlx4/kernel/hca/fw.c (revision 1822)
+++ hw/mlx4/kernel/hca/fw.c (working copy)
@@ -405,7 +405,7 @@
  UNREFERENCED_PARAMETER(num_handles);
 
     if(!p_umv_buf ) {
-#if WORKAROUND_POLL_EQ
+#if 1//WORKAROUND_POLL_EQ
   if ((p_ci_op->command == FW_POLL_EQ_START) || (p_ci_op->command ==
FW_POLL_EQ_STOP)){ // poll EQ (in case of missed interrupt) 
    mlnx_hca_t *p_hca = (mlnx_hca_t *)h_ca;
    struct ib_device *p_ibdev = hca2ibdev(p_hca);
Index: hw/mlx4/kernel/inc/vc.h
===================================================================
--- hw/mlx4/kernel/inc/vc.h (revision 1822)
+++ hw/mlx4/kernel/inc/vc.h (working copy)
@@ -51,7 +51,7 @@
 #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 @@
 } uplink_info_t;
 
 
+
Index: hw/mthca/kernel/hca_driver.c
===================================================================
--- hw/mthca/kernel/hca_driver.c (revision 1822)
+++ hw/mthca/kernel/hca_driver.c (working copy)
@@ -85,6 +85,7 @@
 char   mlnx_uvp_lib_name[MAX_LIB_NAME] = {"mthcau"};
 
 void reregister_hca( hca_dev_ext_t *p_ext );
+void mlnx_poll_eq(struct ib_device *device, BOOLEAN bStart);
 
 
 NTSTATUS
@@ -671,8 +672,28 @@
  UNREFERENCED_PARAMETER(num_handles);
 
  if( !p_umv_buf )
-  return IB_UNSUPPORTED;
+ {
+#if 1//WORKAROUND_POLL_EQ
+  if ((p_ci_op->command == FW_POLL_EQ_START) || (p_ci_op->command ==
FW_POLL_EQ_STOP))
+  { // poll EQ (in case of missed interrupt) 
+   struct ib_device *ib_dev;
+   p_hob = (mlnx_hob_t *)h_ca;
+   ib_dev = IBDEV_FROM_HOB( p_hob );
 
+   if(p_ci_op->command == FW_POLL_EQ_START)
+   {
+    mlnx_poll_eq(ib_dev,1);
+   }else
+   {
+    mlnx_poll_eq(ib_dev,0);
+   }
+   return IB_SUCCESS;
+  }
+  else
+#endif
+   return IB_UNSUPPORTED;
+ }
+
  p_context = (struct ib_ucontext *)h_ca;
  p_hob = HOB_FROM_IBDEV( p_context->device );
  p_ext = EXT_FROM_HOB(p_hob);
Index: hw/mthca/kernel/hca_driver.h
===================================================================
--- hw/mthca/kernel/hca_driver.h (revision 1822)
+++ hw/mthca/kernel/hca_driver.h (working copy)
@@ -214,6 +214,11 @@
 #define FW_OPEN_IF  0xe7
 #define FW_CLOSE_IF  0x7e
 
+#if 1//WORKAROUND_POLL_EQ
+#define FW_POLL_EQ_START  0x0D
+#define FW_POLL_EQ_STOP   0x0E
+#endif
+
 #define FW_SIGNATURE  (0x5a445a44)
 #define FW_SECT_SIZE  (0x10000)
 
Index: hw/mthca/kernel/mthca_dev.h
===================================================================
--- hw/mthca/kernel/mthca_dev.h (revision 1822)
+++ hw/mthca/kernel/mthca_dev.h (working copy)
@@ -229,6 +229,12 @@
  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: hw/mthca/kernel/mthca_eq.c
===================================================================
--- hw/mthca/kernel/mthca_eq.c (revision 1822)
+++ hw/mthca/kernel/mthca_eq.c (working copy)
@@ -596,6 +596,101 @@
 }
 #endif
 
+#if 1//WORKAROUND_POLL_EQ
+
+BOOLEAN
+IsrSynchronizeRoutine(
+ IN PVOID  SynchronizeContext
+ )
+{
+ struct mthca_dev *dev = (struct mthca_dev *)SynchronizeContext;
+
+ //Is this always correct?
+ mthca_arbel_interrupt(dev->ext->int_obj,dev);
+    
+ return TRUE;
+}
+
+
+VOID eq_polling_thread(void *ctx) 
+{
+#define POLLING_INTERVAL_MS 50
+ NTSTATUS status;
+ struct mthca_dev *dev = (struct mthca_dev *)ctx;
+ PVOID wait_objects[2];
+ LARGE_INTEGER  wait_time;
+
+ wait_objects[0] = &dev->eq_table.thread_stop_event;
+ wait_objects[1] = &dev->eq_table.thread_start_event;
+
+ for(;;){
+
+  /* before start polling */
+  DbgPrint("Before polling.\n");
+  for (;;) {
+   status = KeWaitForMultipleObjects( 2, wait_objects, 
+              WaitAny, Executive, KernelMode, FALSE, NULL, NULL );
+
+   if ( status == STATUS_WAIT_0 ){/* thread stopped */
+    DbgPrint("Signaled to stop polling.\n");
+    break;  
+   }
+
+   /* start polling */
+   if ( status == STATUS_WAIT_1 ){
+    DbgPrint("Signaled to start polling.\n");
+    break;  
+   }
+
+  }
+
+  if(dev->eq_table.bTerminated) break;
+  if ( status == STATUS_WAIT_0 ) continue;/* thread stopped, wait for
start again */
+
+  /* polling */
+  DbgPrint("Start polling.\n");
+  wait_time.QuadPart = -(int64_t)(((uint64_t)POLLING_INTERVAL_MS) *
10000);
+  for (;;) {
+   //mlx4_interrupt( NULL, &priv->dev );
+   KeSynchronizeExecution(dev->ext->int_obj, IsrSynchronizeRoutine,
dev);
+
+   status = KeWaitForSingleObject( &dev->eq_table.thread_stop_event, 
+           Executive, KernelMode, FALSE, &wait_time );
+   if ( status == STATUS_SUCCESS ) {
+    //KeClearEvent(&priv->eq_table.thread_stop_event);
+    DbgPrint("Signaled to stop polling while in polling mode.\n");
+    break;  /* thread stopped */
+   }
+  }
+
+  if(dev->eq_table.bTerminated) break;
+ }
+
+ DbgPrint("Polling thread terminated.\n");
+ PsTerminateSystemThread(STATUS_SUCCESS);
+
+}
+
+
+void mlnx_poll_eq(struct ib_device *device, BOOLEAN bStart)
+{
+ LONG signalled=0;
+ struct mthca_dev *dev = (struct mthca_dev *)(device);
+
+ if(bStart){
+  /* signal start of polling */
+  signalled = KeSetEvent(  
+   &dev->eq_table.thread_start_event, IO_NO_INCREMENT, FALSE );
+ }else{
+  /* signal end of polling */
+  signalled = KeSetEvent(  
+   &dev->eq_table.thread_stop_event, IO_NO_INCREMENT, FALSE );
+ }
+
+}
+
+#endif
+
 static int mthca_create_eq(struct mthca_dev *dev,
          int nent,
          u8 intr,
@@ -1061,6 +1156,39 @@
   else
    tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
 
+#if 1//WORKAROUND_POLL_EQ
+ { /* Create a thread for polling EQs in case of missing interrupts
from the card  */
+  NTSTATUS status;
+  OBJECT_ATTRIBUTES attr;
+  HANDLE  handle;
+
+  KeInitializeEvent(&dev->eq_table.thread_start_event,
SynchronizationEvent, FALSE);
+  KeInitializeEvent(&dev->eq_table.thread_stop_event,
SynchronizationEvent, FALSE);
+  dev->eq_table.bTerminated = FALSE;
+  dev->eq_table.threadObject = NULL;
+  InitializeObjectAttributes( &attr, NULL, OBJ_KERNEL_HANDLE, NULL,
NULL );
+  status = PsCreateSystemThread( &handle, 
+   THREAD_ALL_ACCESS, &attr, NULL, NULL, eq_polling_thread, dev );
+  if (NT_SUCCESS(status)) {
+   status = ObReferenceObjectByHandle(
+    handle,
+    THREAD_ALL_ACCESS,
+    NULL,
+    KernelMode,
+    &dev->eq_table.threadObject,
+    NULL
+    );
+
+   ASSERT(status == STATUS_SUCCESS); //
+
+   status = ZwClose(handle);
+
+   ASSERT(NT_SUCCESS(status)); // Should always succeed
+
+  }
+ }
+#endif
+
  return 0;
 
 err_out_cmd:
@@ -1086,6 +1214,33 @@
  u8 status;
  int i;
 
+#if 1//WORKAROUND_POLL_EQ
+ /* stop the EQ polling thread */
+ if (dev->eq_table.threadObject) { 
+  #define WAIT_TIME_MS 3000
+  NTSTATUS status;
+  LARGE_INTEGER  wait_time;
+  LONG signalled;
+
+  dev->eq_table.bTerminated = TRUE;
+
+  /* signal polling stopped in case it is not */
+  signalled = KeSetEvent(  
+   &dev->eq_table.thread_stop_event, IO_NO_INCREMENT, FALSE );
+
+  /* wait for completion of the thread */
+  wait_time.QuadPart = -(int64_t)(((uint64_t)WAIT_TIME_MS) * 10000);
+  status = KeWaitForSingleObject( dev->eq_table.threadObject,
+   Executive, KernelMode, FALSE, &wait_time );
+  ASSERT(status == STATUS_SUCCESS);
+
+  ObDereferenceObject(dev->eq_table.threadObject);
+
+  /* cleanup */
+  dev->eq_table.threadObject = NULL;
+ }
+#endif
+
  mthca_free_irqs(dev);
 
  mthca_MAP_EQ(dev, async_mask(dev),

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20090115/e8f22871/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: int-polling1.patch
Type: application/octet-stream
Size: 10413 bytes
Desc: int-polling1.patch
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20090115/e8f22871/attachment.obj>


More information about the ofw mailing list