<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=us-ascii" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 8.00.6001.18702"></HEAD>
<BODY>
<DIV><SPAN class=719572412-18102009><FONT color=#0000ff size=2 
face=Arial>Applied on 2488.</FONT></SPAN></DIV>
<DIV><SPAN class=719572412-18102009><FONT color=#0000ff size=2 
face=Arial></FONT></SPAN> </DIV>
<DIV><SPAN class=719572412-18102009><FONT color=#0000ff size=2 
face=Arial>Thanks</FONT></SPAN></DIV>
<DIV><SPAN class=719572412-18102009><FONT color=#0000ff size=2 
face=Arial>Tzachi</FONT></SPAN></DIV><BR>
<BLOCKQUOTE 
style="BORDER-LEFT: #0000ff 2px solid; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; MARGIN-RIGHT: 0px" 
dir=ltr>
  <DIV dir=ltr lang=en-us class=OutlookMessageHeader align=left>
  <HR tabIndex=-1>
  <FONT size=2 face=Tahoma><B>From:</B> ofw-bounces@lists.openfabrics.org 
  [mailto:ofw-bounces@lists.openfabrics.org] <B>On Behalf Of </B>Tzachi 
  Dar<BR><B>Sent:</B> Thursday, October 15, 2009 8:02 PM<BR><B>To:</B> 
  ofw@lists.openfabrics.org<BR><B>Subject:</B> [ofw] patch: [WSD] Add APM 
  failback support for WSD<BR></FONT><BR></DIV>
  <DIV></DIV>
  <DIV><FONT size=2 face=Arial><SPAN class=632185917-15102009>The following code 
  allows WSD to load new apm paths after a failure in an existing 
  path.</SPAN></FONT></DIV>
  <DIV><FONT size=2 face=Arial><SPAN 
  class=632185917-15102009></SPAN></FONT> </DIV>
  <DIV><FONT size=2 face=Arial><SPAN 
  class=632185917-15102009>Thanks</SPAN></FONT></DIV>
  <DIV><FONT size=2 face=Arial><SPAN 
  class=632185917-15102009>Tzachi</SPAN></FONT></DIV>
  <DIV><FONT size=2 face=Arial></FONT> </DIV>
  <DIV><FONT size=2 face=Arial></FONT> </DIV>
  <DIV><FONT size=2 face=Arial></FONT> </DIV>
  <DIV><FONT size=2 face=Arial>Index: 
  ib_cm.c<BR>===================================================================<BR>--- 
  ib_cm.c (revision 4959)<BR>+++ ib_cm.c (working copy)<BR>@@ -43,7 
  +43,7 @@<BR> static void AL_API cm_rej_callback(IN ib_cm_rej_rec_t * 
  p_cm_rej_rec);<BR> static void AL_API cm_mra_callback(IN ib_cm_mra_rec_t 
  * p_cm_mra_rec);<BR> static void AL_API cm_dreq_callback(IN 
  ib_cm_dreq_rec_t * p_cm_dreq_rec);<BR>-static void AL_API cm_apr_callback(IN 
  ib_cm_apr_rec_t * p_cm_apr_rec);<BR>+void AL_API cm_apr_callback(IN 
  ib_cm_apr_rec_t * p_cm_apr_rec);<BR> <BR> <BR> /* Computes a 
  service ID for a port. */<BR>@@ -585,19 +585,32 @@<BR>  * A 
  user-specified callback that is invoked after receiving a load<BR>  * 
  alternate path response message.<BR>  */<BR>-static void AL_API<BR>+void 
  AL_API<BR> cm_apr_callback(<BR>  IN    ib_cm_apr_rec_t    *p_cm_apr_rec 
  )<BR> {<BR>- /* TODO */<BR>+ struct ibsp_socket_info 
  *socket_info =<BR>+  (struct ibsp_socket_info 
  *)p_cm_apr_rec->qp_context;<BR>+<BR>  IBSP_ENTER( IBSP_DBG_CM 
  );<BR> <BR>- UNUSED_PARAM( p_cm_apr_rec 
  );<BR>+ IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION, IBSP_DBG_APM, 
  ("cm_apr_callback called p_cm_apr_rec->cm_status = %d\n", 
  p_cm_apr_rec->cm_status) );<BR> <BR>- IBSP_ERROR( ("not 
  implemented") );<BR>+ cl_spinlock_acquire( &g_ibsp.socket_info_mutex 
  );<BR>+ CL_ASSERT(socket_info->apm_state == 
  APM_LAP_SENT);<BR> <BR>- CL_ASSERT( 0 );<BR>+ if 
  ((p_cm_apr_rec->cm_status == IB_SUCCESS) && 
  <BR>+  (p_cm_apr_rec->apr_status == 
  IB_SUCCESS)){<BR>+  socket_info->apm_state = 
  APM_ARMED;<BR>+  socket_info->SuccesfulMigrations++;<BR>+ } 
  else {<BR>+  socket_info->apm_state = 
  APM_MIGRATED;<BR>+ }<BR>+ cl_spinlock_release( 
  &g_ibsp.socket_info_mutex 
  );<BR> <BR>+<BR>+<BR>+<BR>  IBSP_EXIT( IBSP_DBG_CM 
  );<BR> }<BR> <BR>@@ -612,15 +625,31 
  @@<BR> cm_lap_callback(<BR>  IN    ib_cm_lap_rec_t    *p_cm_lap_rec 
  )<BR> {<BR>- /* TODO */<BR>+ ib_cm_apr_t 
  cm_apr;<BR>+ struct ibsp_socket_info *socket_info 
  =<BR>+  (struct ibsp_socket_info 
  *)p_cm_lap_rec->qp_context;<BR>+ <BR>+ ib_api_status_t status;<BR>+<BR>  IBSP_ENTER( 
  IBSP_DBG_CM );<BR> <BR>- UNUSED_PARAM( p_cm_lap_rec 
  );<BR>+ IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION, IBSP_DBG_APM, ("called 
  \n") );<BR> <BR>- IBSP_ERROR( ("not implemented") 
  );<BR> <BR>- CL_ASSERT( 0 );<BR>+ cl_memclr(&cm_apr,  
  sizeof(cm_apr));<BR>+ cm_apr.qp_type = 
  IB_QPT_RELIABLE_CONN;<BR>+ cm_apr.h_qp = 
  socket_info->qp;<BR> <BR>+<BR>+ status = 
  ib_cm_apr(p_cm_lap_rec->h_cm_lap, &cm_apr);<BR>+ if( status != 
  IB_SUCCESS ) {<BR>+  // Actually not much that we can do at this 
  stage.<BR>+  // The other side will get timeout and 
  retry<BR>+  CL_ASSERT(FALSE);<BR>+  IBSP_ERROR( 
  ("ib_cm_apr returned %s\n", ib_get_err_str( status )) 
  );<BR>+ }<BR>+<BR>+<BR>  IBSP_EXIT( IBSP_DBG_CM 
  );<BR> }<BR> <BR>Index: 
  ibsp_iblow.c<BR>===================================================================<BR>--- 
  ibsp_iblow.c (revision 4959)<BR>+++ ibsp_iblow.c (working 
  copy)<BR>@@ -1054,7 +1054,7 @@<BR>  qp_create.sq_signaled = 
  TRUE;<BR> <BR>  status = ib_create_qp( socket_info->hca_pd, 
  &qp_create, socket_info, /* context */<BR>-  NULL, /* 
  async handler */<BR>+  qp_event_handler, /* async handler 
  */<BR>   &socket_info->qp );<BR>  if( status 
  )<BR>  {<BR>Index: 
  ibsp_ip.c<BR>===================================================================<BR>--- 
  ibsp_ip.c (revision 4959)<BR>+++ ibsp_ip.c (working copy)<BR>@@ 
  -418,7 +418,7 @@<BR>  return 
  0;<BR> <BR> error:<BR>- IBSP_ERROR_EXIT( ("query_ip_address 
  failed\n") );<BR>+ IBSP_ERROR_EXIT( ("query_pr failed\n") 
  );<BR>  return 1;<BR> }<BR> <BR>Index: 
  ibsp_mngt.c<BR>===================================================================<BR>--- 
  ibsp_mngt.c (revision 4959)<BR>+++ ibsp_mngt.c (working copy)<BR>@@ 
  -1,289 +0,0 @@<BR>-/* <BR>- * FileName: ibsp_mngt.c<BR>- * <BR>- * 
  Copyright (c)<BR>- * <BR>- * Abstract: Hardware ressource management (HCA and 
  ports).<BR>- * <BR>- * Author:<BR>- * <BR>- * Revision History:<BR>- * <BR>- 
  */<BR>-<BR>-#include "ibspdll.h"<BR>-<BR>-/* Build a list of IP addresses 
  associated with a port */<BR>-int<BR>-build_port_ip_list(IN struct ibsp_port 
  *port)<BR>-{<BR>- struct ibsp_ip_addr *ip_addr;<BR>- cl_list_item_t 
  *item;<BR>- int ret;<BR>-<BR>- CL_ENTER(IBSP_DBG_HW, 
  gdbg_lvl);<BR>- CL_TRACE(IBSP_DBG_HW, gdbg_lvl,<BR>-    
  ("build_port_ip_list for port %UI64x\n", 
  cl_ntoh64(port->guid)));<BR>-<BR>- cl_qlist_init(&port->ip_list);<BR>-<BR>- ret 
  = query_ip_address(port, &port->ip_list);<BR>- if (ret) 
  {<BR>-  CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("query_ip_address failed 
  (%d)\n", ret));<BR>-  goto 
  error;<BR>- }<BR>-<BR>- CL_EXIT(IBSP_DBG_HW, 
  gdbg_lvl);<BR>- return 0;<BR>-<BR>-  error:<BR>- /* Free the 
  list */<BR>- while((item = cl_qlist_remove_head(&port->ip_list)) 
  != cl_qlist_end(&port->ip_list)) {<BR>-<BR>-  ip_addr = 
  PARENT_STRUCT(item, struct ibsp_ip_addr, 
  item);<BR>-<BR>-  HeapFree(g_ibsp.heap, 0, 
  ip_addr);<BR>- }<BR>-<BR>- CL_EXIT_ERROR(IBSP_DBG_HW, 
  gdbg_lvl,<BR>-      ("Failed to build list of IP addr 
  for port %016UI64x\n",<BR>-       
  CL_HTON64(port->guid)));<BR>-<BR>- return 1;<BR>-}<BR>-<BR>-/* Get the 
  info from a port. Link it to the parent HCA. */<BR>-int<BR>-build_port_info(IN 
  struct ibsp_hca *hca,<BR>-    IN ib_net64_t 
  port_guid,<BR>-    IN uint8_t port_num, OUT struct 
  ibsp_port **port_out)<BR>-{<BR>- int ret;<BR>- struct ibsp_port 
  *port;<BR>- cl_list_item_t *item_ip;<BR>-<BR>- CL_ENTER(IBSP_DBG_HW, 
  gdbg_lvl);<BR>-<BR>- port = HeapAlloc(g_ibsp.heap, HEAP_ZERO_MEMORY, 
  sizeof(struct ibsp_port));<BR>-<BR>- if (port == NULL) 
  {<BR>-  CL_ERROR(IBSP_DBG_HW, gdbg_lvl,<BR>-     
  ("HeapAlloc failed (%d)\n", sizeof(struct ibsp_port)));<BR>-  ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-  goto 
  done;<BR>- }<BR>-<BR>- port->guid = 
  port_guid;<BR>- port->port_num = port_num;<BR>- port->hca = 
  hca;<BR>-<BR>- ret = build_port_ip_list(port);<BR>-<BR>- if (ret) 
  {<BR>-  CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("build_port_ip_list failed 
  (%d)\n", ret));<BR>-  ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-  goto 
  done;<BR>- }<BR>-<BR>- /* Insert the new list of IP into the global 
  list of IP addresses. */<BR>- for(item_ip = 
  cl_qlist_head(&port->ip_list);<BR>-  item_ip != 
  cl_qlist_end(&port->ip_list); item_ip = cl_qlist_next(item_ip)) 
  {<BR>-<BR>-  struct ibsp_ip_addr *ip = PARENT_STRUCT(item_ip, struct 
  ibsp_ip_addr, 
  item);<BR>-<BR>-  cl_qlist_insert_tail(&g_ibsp.ip_list, 
  &ip->item_global);<BR>- }<BR>-<BR>- *port_out = 
  port;<BR>-<BR>- CL_EXIT(IBSP_DBG_HW, gdbg_lvl);<BR>-<BR>- ret = 
  0;<BR>-<BR>-  done:<BR>- if (ret) 
  {<BR>-  HeapFree(g_ibsp.heap, 0, 
  port);<BR>- }<BR>-<BR>- CL_EXIT(IBSP_DBG_HW, 
  gdbg_lvl);<BR>-<BR>- return ret;<BR>-}<BR>-<BR>-/* Open and query the HCA 
  for its ports */<BR>-int<BR>-build_hca_info(IN ib_net64_t hca_guid, OUT struct 
  ibsp_hca **hca_out)<BR>-{<BR>- struct ibsp_hca *hca = 
  NULL;<BR>- ib_ca_attr_t *ca_attr = NULL;<BR>- size_t ca_attr_size = 
  0;<BR>- uint8_t port_num;<BR>- int ret;<BR>- ib_api_status_t 
  status;<BR>-<BR>- CL_ENTER(IBSP_DBG_HW, gdbg_lvl);<BR>-<BR>- hca = 
  HeapAlloc(g_ibsp.heap, HEAP_ZERO_MEMORY, sizeof(struct 
  ibsp_hca));<BR>- if (hca == NULL) {<BR>-  CL_ERROR(IBSP_DBG_HW, 
  gdbg_lvl,<BR>-     ("can't get enough memory (%d)\n", 
  sizeof(struct ibsp_hca)));<BR>-  ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-  goto 
  done;<BR>- }<BR>-<BR>- hca->guid = 
  hca_guid;<BR>- cl_qlist_init(&hca->ports_list);<BR>-<BR>- status 
  = ib_open_ca(g_ibsp.al_handle, hca->guid, NULL, /* event handler 
  */<BR>-      NULL, /* context 
  */<BR>-      &hca->hca_handle);<BR>-<BR>- if 
  (status != IB_SUCCESS) {<BR>-  CL_ERROR(IBSP_DBG_HW, gdbg_lvl, 
  ("ib_open_ca failed (%d)\n", status));<BR>-  ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-  goto 
  done;<BR>- }<BR>-<BR>- /* Build the list of ports of each HCAs 
  */<BR>-  query_ca_again:<BR>- status = 
  ib_query_ca(hca->hca_handle, ca_attr, &ca_attr_size);<BR>-<BR>- if 
  (status == IB_INSUFFICIENT_MEMORY) 
  {<BR>-<BR>-  CL_TRACE(IBSP_DBG_HW, gdbg_lvl, ("ib_query_ca needs %d 
  bytes\n", ca_attr_size));<BR>-<BR>-  /* Allocate more memory 
  */<BR>-  if (ca_attr) {<BR>-   HeapFree(g_ibsp.heap, 
  0, ca_attr);<BR>-  }<BR>-<BR>-  ca_attr = 
  HeapAlloc(g_ibsp.heap, 0, ca_attr_size);<BR>-<BR>-  if 
  (ca_attr)<BR>-   goto query_ca_again;<BR>-  else 
  {<BR>-   CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("HeapAlloc 
  failed\n"));<BR>-   ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-   goto 
  done;<BR>-  }<BR>- } else if (status != IB_SUCCESS) 
  {<BR>-  CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("ib_query_ca failed 
  (%d)\n", status));<BR>-  ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-  goto 
  done;<BR>- }<BR>-<BR>- CL_TRACE(IBSP_DBG_HW, gdbg_lvl, ("found %d 
  port on that HCA\n", ca_attr->num_ports));<BR>-<BR>- for(port_num = 0; 
  port_num < ca_attr->num_ports; port_num++) {<BR>-  struct 
  ibsp_port *port;<BR>-<BR>-  ret = build_port_info(hca, 
  ca_attr->p_port_attr[port_num].port_guid, port_num + 1, /* TODO: 
  correct or should query port info? 
  */<BR>-         
  &port);<BR>-  if (ret) 
  {<BR>-   CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("build_port_info 
  failed (%d)\n", ret));<BR>-   goto 
  done;<BR>-  }<BR>-<BR>-  cl_qlist_insert_tail(&hca->ports_list, 
  &port->item);<BR>- }<BR>-<BR>- *hca_out = 
  hca;<BR>-<BR>- ret = 0;<BR>-<BR>-  done:<BR>- if (ca_attr) 
  {<BR>-  HeapFree(g_ibsp.heap, 0, 
  ca_attr);<BR>- }<BR>-<BR>- if (ret) {<BR>-  if (hca) 
  {<BR>-<BR>-   if (hca->hca_handle) 
  {<BR>-    status = ib_close_ca(hca->hca_handle, 
  NULL);<BR>-<BR>-    if (status != IB_SUCCESS) 
  {<BR>-     CL_ERROR(IBSP_DBG_HW, 
  gdbg_lvl,<BR>-        ("ib_close_ca failed 
  (%d)\n", 
  status));<BR>-    }<BR>-   }<BR>-<BR>-   HeapFree(g_ibsp.heap, 
  0, 
  hca);<BR>-  }<BR>- }<BR>-<BR>- CL_TRACE_EXIT(IBSP_DBG_HW, 
  gdbg_lvl, ("return code is %d\n", ret));<BR>-<BR>- return 
  ret;<BR>-}<BR>-<BR>-/* Build the HCA tree. This allows for hotplug. Each HCA 
  is<BR>- * discovered, as well as each ports. 
  */<BR>-int<BR>-build_hca_tree(void)<BR>-{<BR>- ib_net64_t *guid_list = 
  NULL;<BR>- ib_api_status_t status;<BR>- int ret;<BR>- unsigned 
  int hca_num;<BR>- size_t 
  adapter_count;<BR>-<BR>- CL_ENTER(IBSP_DBG_HW, 
  gdbg_lvl);<BR>-<BR>- /* Get the GUIDS of the adapters, so we can open 
  them */<BR>- status = ib_get_ca_guids(g_ibsp.al_handle, NULL, 
  &adapter_count);<BR>- if (status != IB_INSUFFICIENT_MEMORY) 
  {<BR>-  CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("first ib_get_ca_guids 
  failed\n"));<BR>-  ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-  goto 
  done;<BR>- }<BR>-<BR>- /* Make sure we have a reasonable number of 
  HCAs */<BR>- CL_ASSERT(adapter_count < 10);<BR>-<BR>- guid_list = 
  HeapAlloc(g_ibsp.heap, 0, sizeof(ib_net64_t) * adapter_count);<BR>- if 
  (guid_list == NULL) {<BR>-  CL_ERROR(IBSP_DBG_HW, 
  gdbg_lvl,<BR>-     ("can't get enough memory (%d, %d)\n", 
  sizeof(ib_net64_t),<BR>-      
  adapter_count));<BR>-  ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-  goto 
  done;<BR>- }<BR>-<BR>- status = ib_get_ca_guids(g_ibsp.al_handle, 
  guid_list, &adapter_count);<BR>- if (status != IB_SUCCESS) 
  {<BR>-  CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("second ib_get_ca_guids 
  failed (%d)\n", status));<BR>-  ret = 
  WSAEPROVIDERFAILEDINIT;<BR>-  goto 
  done;<BR>- }<BR>-<BR>- CL_TRACE(IBSP_DBG_HW, gdbg_lvl, ("got %d 
  adapter guid(s)\n", adapter_count));<BR>-<BR>- for(hca_num = 0; hca_num 
  < adapter_count; hca_num++) {<BR>-<BR>-  struct ibsp_hca 
  *hca;<BR>-<BR>-  ret = build_hca_info(guid_list[hca_num], 
  &hca);<BR>-  if (ret) 
  {<BR>-   CL_ERROR(IBSP_DBG_HW, gdbg_lvl, ("build_hca_info 
  failed (%d)\n", ret));<BR>-   goto 
  done;<BR>-  }<BR>-<BR>-  cl_qlist_insert_tail(&g_ibsp.hca_list, 
  &hca->item);<BR>- }<BR>-<BR>- CL_ASSERT(adapter_count == 
  cl_qlist_count(&g_ibsp.hca_list));<BR>-<BR>- CL_EXIT(IBSP_DBG_HW, 
  gdbg_lvl);<BR>-<BR>- ret = 0;<BR>-<BR>-  done:<BR>- if 
  (guid_list) {<BR>-  HeapFree(g_ibsp.heap, 0, 
  guid_list);<BR>- }<BR>-<BR>- CL_EXIT(IBSP_DBG_HW, 
  gdbg_lvl);<BR>-<BR>- return ret;<BR>-}<BR>Index: 
  ibspdebug.h<BR>===================================================================<BR>--- 
  ibspdebug.h (revision 4959)<BR>+++ ibspdebug.h (working copy)<BR>@@ 
  -70,10 +70,10 @@<BR>  WPP_DEFINE_BIT( IBSP_DBG_HW) 
  \<BR>  WPP_DEFINE_BIT( IBSP_DBG_IO) \<BR>  WPP_DEFINE_BIT( 
  IBSP_DBG_DUP) \<BR>- WPP_DEFINE_BIT( 
  IBSP_DBG_PERFMON))<BR>+ WPP_DEFINE_BIT( IBSP_DBG_PERFMON) 
  \<BR>+ WPP_DEFINE_BIT( 
  IBSP_DBG_APM))<BR> <BR> <BR>-<BR> #define 
  WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && 
  WPP_CONTROL(WPP_BIT_ ## flags).Level  >= lvl)<BR> #define 
  WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)<BR> #define 
  WPP_FLAG_ENABLED(flags)(WPP_LEVEL_ENABLED(flags) && 
  WPP_CONTROL(WPP_BIT_ ## flags).Level  >= TRACE_LEVEL_VERBOSE)<BR>@@ 
  -123,10 +123,11 @@<BR> #define 
  IBSP_DBG_CONN  0x00000100 /* connections */<BR> #define 
  IBSP_DBG_OPT  0x00000200 /* socket options */<BR> #define 
  IBSP_DBG_NEV  0x00000400 /* network events */<BR>-#define 
  IBSP_DBG_HW  0x00000800 /* Hardware */<BR>+#define 
  IBSP_DBG_HW   0x00000800 /* Hardware */<BR> #define 
  IBSP_DBG_IO   0x00001000 /* Overlapped I/O request 
  */<BR> #define IBSP_DBG_DUP  0x00002000 /* Socket 
  Duplication */<BR> #define IBSP_DBG_PERFMON 0x00004000 /* 
  Performance Monitoring */<BR>+#define 
  IBSP_DBG_APM  0x00008000 /* APM handeling 
  */<BR> <BR> #define IBSP_DBG_ERROR  (CL_DBG_ERROR | 
  IBSP_DBG_ERR)<BR> <BR>Index: 
  ibspdll.c<BR>===================================================================<BR>--- 
  ibspdll.c (revision 4959)<BR>+++ ibspdll.c (working copy)<BR>@@ 
  -73,6 +73,9 @@<BR> uint32_t    g_ibsp_dbg_level = 
  TRACE_LEVEL_ERROR;<BR> uint32_t    g_ibsp_dbg_flags = 
  0x1;<BR> <BR>+BOOL InitApmLib();<BR>+VOID 
  ShutDownApmLib();<BR>+<BR> /*<BR>  * Function: DllMain<BR>  * 
  <BR>@@ -228,6 +231,11 @@<BR>   if( init_globals() 
  )<BR>    return FALSE;<BR> <BR>+  if 
  (g_use_APM)<BR>+  {<BR>+   InitApmLib();<BR>+   // 
  We continue weather it succeeded or not<BR>+  }<BR> #ifdef 
  PERFMON_ENABLED<BR>   IBSPPmInit();<BR> #endif<BR>@@ 
  -827,6 +835,8 @@<BR>  IBSP_PRINT(TRACE_LEVEL_INFORMATION, 
  IBSP_DBG_CONN,<BR>   ("lpCallerData=%p, lpCalleeData=%p\n", 
  lpCallerData, lpCalleeData) 
  );<BR> <BR>+<BR>+ socket_info->active_side = 
  TRUE;<BR>  /* Sanity checks */<BR>  if( lpCallerData 
  )<BR>  {<BR>@@ -872,6 +882,7 @@<BR>   *lpErrno = 
  g_connect_err;<BR>   return 
  SOCKET_ERROR;<BR>  }<BR>+ socket_info->dest_port_guid = 
  dest_port_guid;<BR> <BR>  IBSP_PRINT(TRACE_LEVEL_INFORMATION, 
  IBSP_DBG_CONN, ("got GUID %I64x for IP %s\n",<BR>   CL_NTOH64( 
  dest_port_guid ), inet_ntoa( addr->sin_addr )) );<BR>@@ -1766,6 +1777,19 
  @@<BR> }<BR> <BR> <BR>+void print_cur_apm_state(ib_qp_handle_t 
  h_qp)<BR>+{<BR>+ ib_qp_attr_t qp_attr;<BR>+ char *apm_states[] = { 
  "IB_APM_MIGRATED", "IB_APM_REARM", "IB_APM_ARMED" };<BR>+<BR>+ if 
  (!ib_query_qp(h_qp, &qp_attr)) {<BR>+  IBSP_ERROR(("Querying QP 
  returned that APM FSM is %s (%d)\n", 
  <BR>+   (qp_attr.apm_state<1 || qp_attr.apm_state>3) ? 
  "UNKNOWN" : <BR>+   apm_states[qp_attr.apm_state-1], 
  qp_attr.apm_state));<BR>+ }<BR>+ Sleep(10);<BR>+}<BR>+<BR> /* 
  Function: IBSPSend<BR>  *<BR>  *  Description:<BR>@@ -2230,6 
  +2254,7 @@<BR>  if( g_ibsp.entry_count == 0 
  )<BR>  {<BR>   IBSP_PRINT(TRACE_LEVEL_INFORMATION, 
  IBSP_DBG_INIT, ("entry_count is 0 => cleaning up\n") 
  );<BR>+  ShutDownApmLib();<BR>   ib_release();<BR> <BR> #ifdef 
  PERFMON_ENABLED<BR>@@ -2350,4 +2375,220 
  @@<BR> }<BR> <BR> <BR>+// TRUE means that all is well with 
  socket, no need to recall it<BR>+BOOL rearm_socket(struct ibsp_socket_info 
  *socket_info)<BR>+{<BR> <BR>+<BR>+ ib_path_rec_t 
  path_rec;<BR>+ ib_cm_lap_t cm_lap;<BR>+ int 
  ret;<BR>+ ib_api_status_t status;<BR>+<BR>+ ib_net64_t 
  dest_port_guid; <BR>+ ib_net64_t 
  src_port_guid;<BR>+<BR>+ CL_ASSERT(socket_info->active_side == 
  TRUE);<BR>+ // Try to send the LAP message:<BR>+<BR>+<BR>+ if 
  ((socket_info->SuccesfulMigrations & 1) == 
  0)<BR>+ {<BR>+  src_port_guid = 
  socket_info->port->guid;<BR>+  dest_port_guid = 
  socket_info->dest_port_guid;<BR>+ }<BR>+ else 
  <BR>+ {<BR>+  src_port_guid = 
  GetOtherPortGuid(socket_info->port->guid);<BR>+  dest_port_guid 
  = 
  GetOtherPortGuid(socket_info->dest_port_guid);<BR>+ }<BR>+  /* 
  Get the path record */<BR>+ ret = query_pr( src_port_guid, 
  dest_port_guid, socket_info->port->hca->dev_id, &path_rec 
  );<BR>+ if(ret != IB_SUCCESS)<BR>+ {<BR>+  IBSP_ERROR( 
  ("query_pr for apm failed\n") );<BR>+  return 
  FALSE;<BR>+ }<BR>+<BR>+ cl_memclr(&cm_lap,  
  sizeof(cm_lap));<BR>+ cm_lap.qp_type = 
  IB_QPT_RELIABLE_CONN;<BR>+ cm_lap.h_qp = 
  socket_info->qp;<BR>+ cm_lap.remote_resp_timeout = 
  ib_path_rec_pkt_life( &path_rec ) + 
  CM_REMOTE_TIMEOUT;<BR>+ cm_lap.p_alt_path = 
  &path_rec;<BR>+ cm_lap.pfn_cm_apr_cb = 
  cm_apr_callback;<BR>+ status = ib_cm_lap(&cm_lap);<BR>+ if( 
  status != IB_SUCCESS )<BR>+ {<BR>+  /* Note: a REJ has been 
  automatically sent. */<BR>+  IBSP_ERROR( ("ib_cm_lap returned %s\n", 
  ib_get_err_str( status )) );<BR>+  return FALSE;<BR>+ } 
  <BR>+ else 
  <BR>+ {<BR>+  IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION, 
  IBSP_DBG_APM, ("ib_cm_lap returned succesfuly\n") 
  );<BR>+  socket_info->apm_state = 
  APM_LAP_SENT;<BR>+ }<BR>+  <BR>+<BR>+ // Actually we 
  always return false, since we need to make sure that the lap <BR>+ // was 
  realy successfull.<BR>+ return FALSE;<BR>+}<BR>+<BR>+<BR>+<BR>+VOID 
  APMCallback(struct ibsp_socket_info 
  *apm_socket_info)<BR>+{<BR>+ cl_list_item_t *socket_item = 
  NULL;<BR>+ BOOL found = FALSE;<BR>+<BR>+ if 
  (g_ibsp.apm_data.hEvent== 0) {<BR>+  // This means that we have 
  failed to start our timer, not much<BR>+  // that we can 
  do.<BR>+  return;<BR>+ }<BR>+<BR>+ <BR>+ // Find our 
  socket and mark it as needs to load a new path.<BR>+ // Avoid race by 
  searching in the list<BR>+ // BUGBUG: Need to have a better solution than 
  this<BR>+ cl_spinlock_acquire( &g_ibsp.socket_info_mutex 
  );<BR>+ for( socket_item = cl_qlist_head( &g_ibsp.socket_info_list 
  );<BR>+  socket_item != cl_qlist_end( &g_ibsp.socket_info_list 
  );<BR>+  socket_item = cl_qlist_next( socket_item ) 
  )<BR>+ {<BR>+  struct ibsp_socket_info *socket_info = 
  NULL;<BR>+  socket_info = PARENT_STRUCT(socket_item, struct 
  ibsp_socket_info, item);<BR>+  if (apm_socket_info == socket_info) 
  {<BR>+   if (apm_socket_info->active_side) 
  {<BR>+    CL_ASSERT(apm_socket_info->apm_state == 
  APM_ARMED);<BR>+    apm_socket_info->apm_state = 
  APM_MIGRATED ;<BR>+   }<BR>+   found = 
  TRUE;<BR>+   break;<BR>+  }<BR>+ }<BR>+ CL_ASSERT(found 
  == TRUE); // The case that we are not found is very 
  rare<BR>+                           
  // and is probably a 
  bug<BR>+<BR>+ SetEvent(g_ibsp.apm_data.hEvent);<BR>+<BR>+ cl_spinlock_release( 
  &g_ibsp.socket_info_mutex );<BR>+<BR>+}<BR>+<BR>+DWORD WINAPI 
  ApmThreadProc(<BR>+  LPVOID lpParameter<BR>+)<BR>+{<BR>+ DWORD 
  dwTimeOut = INFINITE;<BR>+ DWORD ret;<BR>+ cl_list_item_t 
  *socket_item = 
  NULL;<BR>+<BR>+ UNREFERENCED_PARAMETER(lpParameter);<BR>+<BR>+ for(;;) 
  {<BR>+  BOOL AllSocketsDone = TRUE;<BR>+  ret = 
  WaitForSingleObject(g_ibsp.apm_data.hEvent, dwTimeOut);<BR>+  if 
  (g_ibsp.apm_data.ThreadExit) {<BR>+   return 
  0;<BR>+  }  <BR>+  cl_spinlock_acquire( 
  &g_ibsp.socket_info_mutex );<BR>+  for( socket_item = 
  cl_qlist_head( &g_ibsp.socket_info_list 
  );<BR>+   socket_item != cl_qlist_end( 
  &g_ibsp.socket_info_list );<BR>+   socket_item = 
  cl_qlist_next( socket_item ) )<BR>+  {<BR>+   struct 
  ibsp_socket_info *socket_info = NULL;<BR>+   socket_info = 
  PARENT_STRUCT(socket_item, struct ibsp_socket_info, 
  item);<BR>+   if(socket_info->apm_state == 
  APM_MIGRATED)<BR>+   {<BR>+    AllSocketsDone 
  &= rearm_socket(socket_info);<BR>+   } else 
   if(socket_info->apm_state == APM_LAP_SENT) 
  {<BR>+    AllSocketsDone = 
  FALSE;<BR>+   }<BR>+  }<BR>+  if 
  (AllSocketsDone) <BR>+  {<BR>+   dwTimeOut = 
  INFINITE;<BR>+  } <BR>+  else 
  <BR>+  {<BR>+   dwTimeOut = 
  2000;<BR>+  }<BR>+<BR>+  cl_spinlock_release( 
  &g_ibsp.socket_info_mutex 
  );<BR>+<BR>+ <BR>+ }<BR>+}<BR>+<BR>+<BR>+void 
  qp_event_handler(ib_async_event_rec_t *p_event)<BR>+{<BR>+<BR>+ if 
  (p_event->code == IB_AE_QP_APM) <BR>+ {<BR>+  struct 
  ibsp_socket_info  *socket_info = (struct 
  ibsp_socket_info  *)p_event->context;<BR>+  IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION, 
  IBSP_DBG_APM,("Received an APM 
  event\n"));<BR>+  APMCallback(socket_info);<BR>+ }<BR>+}<BR>+<BR>+<BR>+<BR>+BOOL 
  InitApmLib()<BR>+{<BR>+ IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION, 
  IBSP_DBG_APM,("called\n"));<BR>+<BR>+ g_ibsp.apm_data.hEvent = 
  CreateEvent(NULL, FALSE, FALSE, NULL);<BR>+ if (g_ibsp.apm_data.hEvent == 
  NULL) {<BR>+  IBSP_ERROR_EXIT( ("CreateEvent failed with error 
  %d\n", GetLastError()));<BR>+  return 
  FALSE;<BR>+ }<BR>+<BR>+ g_ibsp.apm_data.hThread =  
  CreateThread(<BR>+   NULL,                   
  // Default security 
  attributes<BR>+   0,<BR>+   ApmThreadProc,<BR>+   NULL,<BR>+   0,<BR>+   NULL<BR>+   );      
  <BR>+ if (g_ibsp.apm_data.hThread == NULL) 
  {<BR>+  IBSP_ERROR_EXIT( ("CreateThread failed with error %d\n", 
  GetLastError()));<BR>+  CloseHandle(g_ibsp.apm_data.hEvent);<BR>+  g_ibsp.apm_data.hEvent 
  = NULL;<BR>+  return FALSE;<BR>+ }<BR>+<BR>+<BR>+ return 
  TRUE;<BR>+<BR>+<BR>+<BR>+}<BR>+<BR>+<BR>+VOID 
  ShutDownApmLib()<BR>+{<BR>+ DWORD dwRet;<BR>+<BR>+ if 
  (g_ibsp.apm_data.hEvent== 0) {<BR>+  // This means that we have 
  failed to start our timer, not much<BR>+  // that we can 
  do.<BR>+  return;<BR>+ }<BR>+<BR>+ g_ibsp.apm_data.ThreadExit 
  = TRUE;<BR>+ SetEvent(g_ibsp.apm_data.hEvent);<BR>+<BR>+ dwRet = 
  WaitForSingleObject(g_ibsp.apm_data.hThread, 
  INFINITE);<BR>+ CL_ASSERT(dwRet == WAIT_OBJECT_0);<BR>+<BR>+ dwRet = 
  CloseHandle(g_ibsp.apm_data.hThread);<BR>+ CL_ASSERT(dwRet != 
  0);<BR>+<BR>+ dwRet = 
  CloseHandle(g_ibsp.apm_data.hEvent);<BR>+ CL_ASSERT(dwRet != 
  0);<BR>+}<BR>+<BR>Index: 
  ibspproto.h<BR>===================================================================<BR>--- 
  ibspproto.h (revision 4959)<BR>+++ ibspproto.h (working copy)<BR>@@ 
  -304,4 +304,8 @@<BR>  return DestPortGuid ^ 
  0x300000000000000;<BR> <BR> }<BR>+void AL_API 
  cm_apr_callback(<BR>+ IN    ib_cm_apr_rec_t    *p_cm_apr_rec 
  );<BR> <BR>+<BR>+void qp_event_handler(ib_async_event_rec_t 
  *p_event);<BR>Index: 
  ibspstruct.h<BR>===================================================================<BR>--- 
  ibspstruct.h (revision 4959)<BR>+++ ibspstruct.h (working 
  copy)<BR>@@ -220,6 +220,15 @@<BR>  struct ibsp_hca 
  *hca;  /* HCA to which this cq belongs. 
  */<BR> };<BR> <BR>+<BR>+enum APM_STATE 
  {<BR>+ APM_ARMED,<BR>+ APM_MIGRATED,<BR>+ APM_LAP_SENT<BR>+<BR>+};<BR>+<BR>+<BR> /* 
  Structure representing the context information stored for each<BR>  * 
  socket created */<BR> struct ibsp_socket_info<BR>@@ -322,6 +331,10 
  @@<BR>   GUID identifier;  /* Unique identifier 
  */<BR>   DWORD dwProcessId;<BR>  } 
  duplicate;<BR>+ BOOL active_side; // Tell if we have started this 
  call<BR>+ enum APM_STATE apm_state;<BR>+ UINT 
  SuccesfulMigrations;<BR>+ ib_net64_t 
  dest_port_guid;<BR> <BR> #ifdef 
  IBSP_LOGGING<BR>  DataLogger  SendDataLogger;<BR>@@ -413,6 
  +426,13 @@<BR>  struct cq_thread_info 
  *cq_tinfo;<BR> };<BR> <BR>+struct 
  apm_data_t<BR>+{<BR>+ HANDLE hThread;<BR>+ HANDLE hEvent;<BR>+ BOOL 
  ThreadExit;<BR>+};<BR>+<BR> /* There is only one instance of that 
  structure. */<BR> struct ibspdll_globals<BR> {<BR>@@ -442,6 +462,8 
  @@<BR>  cl_fmap_t  ip_map;   /* list of all 
  IP addresses supported by all the ports. 
  */<BR>  cl_spinlock_t ip_mutex;<BR> <BR>+ struct 
  apm_data_t apm_data;<BR>+<BR> #ifdef _DEBUG_<BR>  /* Statistics 
  */<BR>  atomic32_t qp_num;<BR></DIV></BLOCKQUOTE></FONT></BODY></HTML>