<!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><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></BODY></HTML>