<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=us-ascii">
<META content="MSHTML 6.00.2900.3243" name=GENERATOR></HEAD>
<BODY>
<DIV><SPAN class=171044813-18012009><FONT face=Arial color=#0000ff 
size=2>Applied in 1841</FONT></SPAN></DIV><BR>
<BLOCKQUOTE dir=ltr 
style="PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #0000ff 2px solid; MARGIN-RIGHT: 0px">
  <DIV class=OutlookMessageHeader lang=en-us dir=ltr align=left>
  <HR tabIndex=-1>
  <FONT face=Tahoma size=2><B>From:</B> ofw-bounces@lists.openfabrics.org 
  [mailto:ofw-bounces@lists.openfabrics.org] <B>On Behalf Of </B>Leonid 
  Keller<BR><B>Sent:</B> Thursday, January 15, 2009 10:21 AM<BR><B>To:</B> 
  ofw@lists.openfabrics.org<BR><B>Subject:</B> [ofw][patch][MLX4, MTHCA] Add 
  polling mode to MTHCA<BR></FONT><BR></DIV>
  <DIV></DIV>
  <DIV><FONT face=Arial size=2><SPAN class=269531008-15012009>This patch is a 
  second part of a workaround, added in rev. 1800 for MLX4.</SPAN></FONT></DIV>
  <DIV><FONT face=Arial size=2><SPAN class=269531008-15012009>It adds polling 
  mode support for MTHCA.</SPAN></FONT></DIV>
  <DIV><FONT face=Arial size=2><SPAN class=269531008-15012009>This is 
  needed for example in the case, when interrupts stop to be conveyed to 
  the driver for some HW problem.</SPAN></FONT></DIV>
  <DIV><FONT face=Arial size=2><SPAN class=269531008-15012009>(Xsigo saw such 
  case).</SPAN></FONT></DIV>
  <DIV><FONT face=Arial size=2><SPAN class=269531008-15012009>This patch 
  additionally "actualize" the workaround (by off-commenting 
  #if WORKAROUND_POLL_EQ) to enable polling mode without re-building the 
  drivers.</SPAN></FONT></DIV>
  <DIV><FONT face=Arial size=2><SPAN 
  class=269531008-15012009></SPAN></FONT> </DIV>
  <DIV><FONT face=Arial size=2><SPAN class=269531008-15012009>Signed-off-by: 
  James Yang [jyang@xsigo.com]</SPAN></FONT></DIV>
  <DIV><FONT face=Arial size=2><SPAN 
  class=269531008-15012009></SPAN></FONT> </DIV>
  <DIV><FONT face=Arial size=2></FONT> </DIV>
  <DIV><FONT face=Arial size=2>Index: 
  hw/mlx4/kernel/bus/ib/main.c<BR>===================================================================<BR>--- 
  hw/mlx4/kernel/bus/ib/main.c (revision 1822)<BR>+++ 
  hw/mlx4/kernel/bus/ib/main.c (working copy)<BR>@@ -38,7 +38,7 
  @@<BR> #include "ib_cache.h"<BR> #include 
  "net\mlx4.h"<BR> <BR>-#if WORKAROUND_POLL_EQ<BR>+#if 1//WORKAROUND_POLL_EQ<BR> void 
  mlx4_poll_eq(struct ib_device *dev, BOOLEAN 
  bStart);<BR> #endif<BR> <BR>@@ -569,7 +569,7 
  @@<BR>  ibdev->ib_dev.x.get_cached_pkey  = 
  ib_get_cached_pkey;<BR>  ibdev->ib_dev.x.register_ev_cb  = 
  mlx4_reset_cb_register;<BR>  ibdev->ib_dev.x.unregister_ev_cb = 
  mlx4_reset_cb_unregister;<BR>-#if WORKAROUND_POLL_EQ<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>  ibdev->ib_dev.x.poll_eq    = 
  mlx4_poll_eq;<BR> #endif<BR>  if 
  (mlx4_is_livefish(ibdev->dev))<BR>Index: 
  hw/mlx4/kernel/bus/inc/ib_verbs_ex.h<BR>===================================================================<BR>--- 
  hw/mlx4/kernel/bus/inc/ib_verbs_ex.h (revision 1822)<BR>+++ 
  hw/mlx4/kernel/bus/inc/ib_verbs_ex.h (working copy)<BR>@@ -52,7 +52,7 
  @@<BR>   u8 port_num, __be16 pkey, u16 
  *index);<BR>  int (*register_ev_cb) (struct ib_event_handler 
  *event_handler);<BR>  int (*unregister_ev_cb) (struct 
  ib_event_handler *event_handler);<BR>-#if WORKAROUND_POLL_EQ<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>  void (*poll_eq)(struct ib_device *device, 
  BOOLEAN bStart);<BR> #endif<BR> };<BR>Index: 
  hw/mlx4/kernel/bus/net/eq.c<BR>===================================================================<BR>--- 
  hw/mlx4/kernel/bus/net/eq.c (revision 1822)<BR>+++ 
  hw/mlx4/kernel/bus/net/eq.c (working copy)<BR>@@ -255,7 +255,7 
  @@<BR>  return (BOOLEAN)work;<BR> }<BR> <BR>-#if 
  WORKAROUND_POLL_EQ<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR> <BR> BOOLEAN<BR> IsrSynchronizeRoutine(<BR>@@ 
  -744,7 +744,7 @@<BR>   eq_set_ci(&priv->eq_table.eq[i], 
  1);<BR> <BR> <BR>-#if WORKAROUND_POLL_EQ<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>  { /* Create a thread for polling EQs in 
  case of missing interrupts from the card  
  */<BR>   NTSTATUS 
  status;<BR>   OBJECT_ATTRIBUTES attr;<BR>@@ -866,7 +866,7 
  @@<BR>  struct mlx4_priv *priv = mlx4_priv(dev);<BR>  int 
  i;<BR> <BR>-#if WORKAROUND_POLL_EQ<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>  /* stop the EQ polling thread 
  */<BR>  if (priv->eq_table.threadObject) { 
  <BR>   #define WAIT_TIME_MS 3000<BR>Index: 
  hw/mlx4/kernel/bus/net/mlx4.h<BR>===================================================================<BR>--- 
  hw/mlx4/kernel/bus/net/mlx4.h (revision 1822)<BR>+++ 
  hw/mlx4/kernel/bus/net/mlx4.h (working copy)<BR>@@ -233,7 +233,7 
  @@<BR>  int   have_irq;<BR>  u8   inta_pin;<BR>  u8      max_extra_eqs;<BR>-#if 
  WORKAROUND_POLL_EQ<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>  KEVENT  thread_start_event;<BR>  KEVENT  thread_stop_event;<BR>  BOOLEAN  bTerminated;<BR>Index: 
  hw/mlx4/kernel/hca/fw.c<BR>===================================================================<BR>--- 
  hw/mlx4/kernel/hca/fw.c (revision 1822)<BR>+++ 
  hw/mlx4/kernel/hca/fw.c (working copy)<BR>@@ -405,7 +405,7 
  @@<BR>  UNREFERENCED_PARAMETER(num_handles);<BR> <BR>     
  if(!p_umv_buf ) {<BR>-#if WORKAROUND_POLL_EQ<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>   if ((p_ci_op->command == 
  FW_POLL_EQ_START) || (p_ci_op->command == FW_POLL_EQ_STOP)){ // poll EQ (in 
  case of missed interrupt) <BR>    mlnx_hca_t *p_hca = 
  (mlnx_hca_t *)h_ca;<BR>    struct ib_device *p_ibdev = 
  hca2ibdev(p_hca);<BR>Index: 
  hw/mlx4/kernel/inc/vc.h<BR>===================================================================<BR>--- 
  hw/mlx4/kernel/inc/vc.h (revision 1822)<BR>+++ 
  hw/mlx4/kernel/inc/vc.h (working copy)<BR>@@ -51,7 +51,7 
  @@<BR> #define FW_OPEN_IF  0xe7<BR> #define 
  FW_CLOSE_IF  0x7e<BR> <BR>-#if WORKAROUND_POLL_EQ<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR> #define 
  FW_POLL_EQ_START  0x0D<BR> #define FW_POLL_EQ_STOP 
    0x0E<BR> #endif<BR>@@ -79,3 +79,4 @@<BR> } 
  uplink_info_t;<BR> <BR> <BR>+<BR>Index: 
  hw/mthca/kernel/hca_driver.c<BR>===================================================================<BR>--- 
  hw/mthca/kernel/hca_driver.c (revision 1822)<BR>+++ 
  hw/mthca/kernel/hca_driver.c (working copy)<BR>@@ -85,6 +85,7 
  @@<BR> char   mlnx_uvp_lib_name[MAX_LIB_NAME] = 
  {"mthcau"};<BR> <BR> void reregister_hca( hca_dev_ext_t *p_ext 
  );<BR>+void mlnx_poll_eq(struct ib_device *device, BOOLEAN 
  bStart);<BR> <BR> <BR> NTSTATUS<BR>@@ -671,8 +672,28 
  @@<BR>  UNREFERENCED_PARAMETER(num_handles);<BR> <BR>  if( 
  !p_umv_buf )<BR>-  return IB_UNSUPPORTED;<BR>+ {<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>+  if ((p_ci_op->command == 
  FW_POLL_EQ_START) || (p_ci_op->command == 
  FW_POLL_EQ_STOP))<BR>+  { // poll EQ (in case of missed interrupt) 
  <BR>+   struct ib_device *ib_dev;<BR>+   p_hob = 
  (mlnx_hob_t *)h_ca;<BR>+   ib_dev = IBDEV_FROM_HOB( p_hob 
  );<BR> <BR>+   if(p_ci_op->command == 
  FW_POLL_EQ_START)<BR>+   {<BR>+    mlnx_poll_eq(ib_dev,1);<BR>+   }else<BR>+   {<BR>+    mlnx_poll_eq(ib_dev,0);<BR>+   }<BR>+   return 
  IB_SUCCESS;<BR>+  }<BR>+  else<BR>+#endif<BR>+   return 
  IB_UNSUPPORTED;<BR>+ }<BR>+<BR>  p_context = (struct 
  ib_ucontext *)h_ca;<BR>  p_hob = HOB_FROM_IBDEV( 
  p_context->device );<BR>  p_ext = EXT_FROM_HOB(p_hob);<BR>Index: 
  hw/mthca/kernel/hca_driver.h<BR>===================================================================<BR>--- 
  hw/mthca/kernel/hca_driver.h (revision 1822)<BR>+++ 
  hw/mthca/kernel/hca_driver.h (working copy)<BR>@@ -214,6 +214,11 
  @@<BR> #define FW_OPEN_IF  0xe7<BR> #define 
  FW_CLOSE_IF  0x7e<BR> <BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>+#define FW_POLL_EQ_START  0x0D<BR>+#define 
  FW_POLL_EQ_STOP   0x0E<BR>+#endif<BR>+<BR> #define 
  FW_SIGNATURE  (0x5a445a44)<BR> #define 
  FW_SECT_SIZE  (0x10000)<BR> <BR>Index: 
  hw/mthca/kernel/mthca_dev.h<BR>===================================================================<BR>--- 
  hw/mthca/kernel/mthca_dev.h (revision 1822)<BR>+++ 
  hw/mthca/kernel/mthca_dev.h (working copy)<BR>@@ -229,6 +229,12 
  @@<BR>  int                
  have_irq;<BR>  u8                 
  inta_pin;<BR>  KLOCK_QUEUE_HANDLE  lockh;<BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>+ KEVENT  thread_start_event;<BR>+ KEVENT  thread_stop_event;<BR>+ BOOLEAN  bTerminated;<BR>+ PVOID  threadObject;<BR>+#endif<BR> };<BR> <BR> struct 
  mthca_cq_table {<BR>Index: 
  hw/mthca/kernel/mthca_eq.c<BR>===================================================================<BR>--- 
  hw/mthca/kernel/mthca_eq.c (revision 1822)<BR>+++ 
  hw/mthca/kernel/mthca_eq.c (working copy)<BR>@@ -596,6 +596,101 
  @@<BR> }<BR> #endif<BR> <BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>+<BR>+BOOLEAN<BR>+IsrSynchronizeRoutine(<BR>+ IN 
  PVOID  SynchronizeContext<BR>+ )<BR>+{<BR>+ struct mthca_dev 
  *dev = (struct mthca_dev *)SynchronizeContext;<BR>+<BR>+ //Is this always 
  correct?<BR>+ mthca_arbel_interrupt(dev->ext->int_obj,dev);<BR>+    
  <BR>+ return TRUE;<BR>+}<BR>+<BR>+<BR>+VOID eq_polling_thread(void *ctx) 
  <BR>+{<BR>+#define POLLING_INTERVAL_MS 50<BR>+ NTSTATUS 
  status;<BR>+ struct mthca_dev *dev = (struct mthca_dev 
  *)ctx;<BR>+ PVOID wait_objects[2];<BR>+ LARGE_INTEGER  
  wait_time;<BR>+<BR>+ wait_objects[0] = 
  &dev->eq_table.thread_stop_event;<BR>+ wait_objects[1] = 
  &dev->eq_table.thread_start_event;<BR>+<BR>+ for(;;){<BR>+<BR>+  /* 
  before start polling */<BR>+  DbgPrint("Before 
  polling.\n");<BR>+  for (;;) {<BR>+   status = 
  KeWaitForMultipleObjects( 2, wait_objects, 
  <BR>+              
  WaitAny, Executive, KernelMode, FALSE, NULL, NULL 
  );<BR>+<BR>+   if ( status == STATUS_WAIT_0 ){/* thread stopped 
  */<BR>+    DbgPrint("Signaled to stop 
  polling.\n");<BR>+    break;  <BR>+   }<BR>+<BR>+   /* 
  start polling */<BR>+   if ( status == STATUS_WAIT_1 
  ){<BR>+    DbgPrint("Signaled to start 
  polling.\n");<BR>+    break;  <BR>+   }<BR>+<BR>+  }<BR>+<BR>+  if(dev->eq_table.bTerminated) 
  break;<BR>+  if ( status == STATUS_WAIT_0 ) continue;/* thread 
  stopped, wait for start again */<BR>+<BR>+  /* polling 
  */<BR>+  DbgPrint("Start 
  polling.\n");<BR>+  wait_time.QuadPart = 
  -(int64_t)(((uint64_t)POLLING_INTERVAL_MS) * 10000);<BR>+  for (;;) 
  {<BR>+   //mlx4_interrupt( NULL, &priv->dev 
  );<BR>+   KeSynchronizeExecution(dev->ext->int_obj, 
  IsrSynchronizeRoutine, dev);<BR>+<BR>+   status = 
  KeWaitForSingleObject( &dev->eq_table.thread_stop_event, 
  <BR>+           Executive, 
  KernelMode, FALSE, &wait_time );<BR>+   if ( status == 
  STATUS_SUCCESS ) 
  {<BR>+    //KeClearEvent(&priv->eq_table.thread_stop_event);<BR>+    DbgPrint("Signaled 
  to stop polling while in polling 
  mode.\n");<BR>+    break;  /* thread stopped 
  */<BR>+   }<BR>+  }<BR>+<BR>+  if(dev->eq_table.bTerminated) 
  break;<BR>+ }<BR>+<BR>+ DbgPrint("Polling thread 
  terminated.\n");<BR>+ PsTerminateSystemThread(STATUS_SUCCESS);<BR>+<BR>+}<BR>+<BR>+<BR>+void 
  mlnx_poll_eq(struct ib_device *device, BOOLEAN bStart)<BR>+{<BR>+ LONG 
  signalled=0;<BR>+ struct mthca_dev *dev = (struct mthca_dev 
  *)(device);<BR>+<BR>+ if(bStart){<BR>+  /* signal start of 
  polling */<BR>+  signalled = KeSetEvent( 
   <BR>+   &dev->eq_table.thread_start_event, 
  IO_NO_INCREMENT, FALSE );<BR>+ }else{<BR>+  /* signal end of 
  polling */<BR>+  signalled = KeSetEvent( 
   <BR>+   &dev->eq_table.thread_stop_event, 
  IO_NO_INCREMENT, FALSE 
  );<BR>+ }<BR>+<BR>+}<BR>+<BR>+#endif<BR>+<BR> static int 
  mthca_create_eq(struct mthca_dev 
  *dev,<BR>          int 
  nent,<BR>          u8 intr,<BR>@@ 
  -1061,6 +1156,39 
  @@<BR>   else<BR>    tavor_eq_req_not(dev, 
  dev->eq_table.eq[i].eqn);<BR> <BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>+ { /* Create a thread for polling EQs in case 
  of missing interrupts from the card  */<BR>+  NTSTATUS 
  status;<BR>+  OBJECT_ATTRIBUTES attr;<BR>+  HANDLE 
   handle;<BR>+<BR>+  KeInitializeEvent(&dev->eq_table.thread_start_event, 
  SynchronizationEvent, 
  FALSE);<BR>+  KeInitializeEvent(&dev->eq_table.thread_stop_event, 
  SynchronizationEvent, FALSE);<BR>+  dev->eq_table.bTerminated = 
  FALSE;<BR>+  dev->eq_table.threadObject = 
  NULL;<BR>+  InitializeObjectAttributes( &attr, NULL, 
  OBJ_KERNEL_HANDLE, NULL, NULL );<BR>+  status = 
  PsCreateSystemThread( &handle, <BR>+   THREAD_ALL_ACCESS, 
  &attr, NULL, NULL, eq_polling_thread, dev );<BR>+  if 
  (NT_SUCCESS(status)) {<BR>+   status = 
  ObReferenceObjectByHandle(<BR>+    handle,<BR>+    THREAD_ALL_ACCESS,<BR>+    NULL,<BR>+    KernelMode,<BR>+    &dev->eq_table.threadObject,<BR>+    NULL<BR>+    );<BR>+<BR>+   ASSERT(status 
  == STATUS_SUCCESS); //<BR>+<BR>+   status = 
  ZwClose(handle);<BR>+<BR>+   ASSERT(NT_SUCCESS(status)); // 
  Should always 
  succeed<BR>+<BR>+  }<BR>+ }<BR>+#endif<BR>+<BR>  return 
  0;<BR> <BR> err_out_cmd:<BR>@@ -1086,6 +1214,33 @@<BR>  u8 
  status;<BR>  int i;<BR> <BR>+#if 
  1//WORKAROUND_POLL_EQ<BR>+ /* stop the EQ polling thread */<BR>+ if 
  (dev->eq_table.threadObject) { <BR>+  #define 
  WAIT_TIME_MS 3000<BR>+  NTSTATUS 
  status;<BR>+  LARGE_INTEGER  wait_time;<BR>+  LONG 
  signalled;<BR>+<BR>+  dev->eq_table.bTerminated = 
  TRUE;<BR>+<BR>+  /* signal polling stopped in case it is not 
  */<BR>+  signalled = KeSetEvent( 
   <BR>+   &dev->eq_table.thread_stop_event, 
  IO_NO_INCREMENT, FALSE );<BR>+<BR>+  /* wait for completion of the 
  thread */<BR>+  wait_time.QuadPart = 
  -(int64_t)(((uint64_t)WAIT_TIME_MS) * 10000);<BR>+  status = 
  KeWaitForSingleObject( 
  dev->eq_table.threadObject,<BR>+   Executive, KernelMode, 
  FALSE, &wait_time );<BR>+  ASSERT(status == 
  STATUS_SUCCESS);<BR>+<BR>+  ObDereferenceObject(dev->eq_table.threadObject);<BR>+<BR>+  /* 
  cleanup */<BR>+  dev->eq_table.threadObject = 
  NULL;<BR>+ }<BR>+#endif<BR>+<BR>  mthca_free_irqs(dev);<BR> <BR>  mthca_MAP_EQ(dev, 
  async_mask(dev),<BR></FONT></DIV></BLOCKQUOTE></BODY></HTML>