<!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>