return NULL;\r
}\r
\r
- node = ib_register_memory( &socket_info->buf_mem_list, socket_info->hca_pd,\r
+ node = ibsp_reg_mem( socket_info, socket_info->hca_pd,\r
lpBuffer, dwBufferLength, access_ctrl, lpErrno );\r
\r
fzprint(("%s():%d:0x%x:0x%x: registering MEM from %p to %p, len %d, handle %p\n",\r
if( node == NULL )\r
{\r
IBSP_ERROR_EXIT(\r
- ("ib_register_memory failed (pd=%p)\n", socket_info->hca_pd) );\r
+ ("ibsp_reg_mem failed (pd=%p)\n", socket_info->hca_pd) );\r
*lpErrno = WSAENOBUFS;\r
}\r
else\r
return SOCKET_ERROR;\r
}\r
\r
- ret = ib_deregister_memory( &socket_info->buf_mem_list, node, lpErrno );\r
-\r
+ ret = ibsp_dereg_mem( socket_info, node, lpErrno );\r
\r
fzprint(("%s():%d:0x%x:0x%x: unregistering MEM %p, mr_num=%d, ret=%d\n",\r
__FUNCTION__,\r
GetCurrentThreadId(), node, g_ibsp.mr_num, ret));\r
\r
IBSP_EXIT( IBSP_DBG_MEM );\r
-\r
return ret;\r
}\r
\r
\r
hca = socket_info->port->hca;\r
\r
- node = ib_register_memory( &hca->rdma_mem_list, hca->pd,\r
+ /** TODO: Fix locking so we dont' dereference node outside of mutex. */\r
+ node = ibsp_reg_mem( socket_info, hca->pd,\r
lpBuffer, dwBufferLength, access_ctrl, lpErrno );\r
\r
- if( node == NULL )\r
+ if( !node )\r
{\r
- IBSP_ERROR_EXIT( ("ib_register_memory failed %d\n", *lpErrno) );\r
+ IBSP_ERROR_EXIT( ("ibsp_reg_mem failed %d\n", *lpErrno) );\r
*lpErrno = WSAENOBUFS;\r
return SOCKET_ERROR;\r
}\r
desc = lpRdmaBufferDescriptor;\r
\r
desc->iova = (uint64_t) (uintptr_t) lpBuffer;\r
- desc->lkey = node->lkey;\r
- desc->rkey = node->rkey;\r
+ desc->lkey = node->p_reg->lkey;\r
+ desc->rkey = node->p_reg->rkey;\r
desc->node = node;\r
\r
*lpErrno = 0;\r
\r
- fzprint(("%s(): registering RDMA MEM from %p to %p, len %d, handle %p\n",\r
- __FUNCTION__, lpBuffer, (unsigned char *)lpBuffer + dwBufferLength,\r
- dwBufferLength, node));\r
+ IBSP_TRACE1( IBSP_DBG_MEM,\r
+ ("Socket %p registered RDMA MEM at %p, len %d, for access %d, "\r
+ "returning handle %p, rkey %08x\n",\r
+ s, lpBuffer, dwBufferLength, dwFlags, node, desc->rkey));\r
\r
IBSP_EXIT( IBSP_DBG_MEM );\r
\r
struct rdma_memory_desc *desc;\r
struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
int ret;\r
- struct ibsp_hca *hca;\r
\r
IBSP_ENTER( IBSP_DBG_MEM );\r
\r
return SOCKET_ERROR;\r
}\r
\r
-\r
CL_ASSERT( lpRdmaBufferDescriptor );\r
\r
if( dwDescriptorLength < sizeof(struct rdma_memory_desc) )\r
\r
desc = lpRdmaBufferDescriptor;\r
\r
- hca = socket_info->port->hca;\r
- ret = ib_deregister_memory( &hca->rdma_mem_list, desc->node, lpErrno );\r
+ ret = ibsp_dereg_mem( socket_info, desc->node, lpErrno );\r
\r
fzprint(("%s():%d:0x%x:0x%x: Unregistering RDMA MEM %p\n",\r
__FUNCTION__, __LINE__, GetCurrentProcessId(),\r
GetCurrentThreadId(), desc->node));\r
\r
IBSP_EXIT( IBSP_DBG_MEM );\r
-\r
return ret;\r
}\r
\r
{\r
local_ds[ds_idx].vaddr = (uint64_t)(void* __ptr64)lpBuffers[ds_idx].buf;\r
local_ds[ds_idx].length = lpBuffers[ds_idx].len;\r
- local_ds[ds_idx].lkey = ((struct memory_node*)lpBuffers[ds_idx].handle)->lkey;\r
+ local_ds[ds_idx].lkey =\r
+ ((struct memory_node*)lpBuffers[ds_idx].handle)->p_reg->lkey;\r
\r
lpOverlapped->InternalHigh += lpBuffers[ds_idx].len;\r
}\r
*lpErrno = WSA_IO_PENDING;\r
\r
IBSP_TRACE1( IBSP_DBG_IO,\r
- ("Posted RDMA: socket=%p, ov=%p, type=%d, local=%p dest=%I64x, len=%d\n",\r
- s, lpOverlapped, wr_type, lpBuffers[0].buf,\r
- send_wr.remote_ops.vaddr, lpBuffers[0].len) );\r
+ ("Posted RDMA: socket=%p, ov=%p, type=%d, local=%p, len=%d, "\r
+ "dest=%016I64x, rkey=%08x\n",\r
+ s, lpOverlapped, wr_type, lpBuffers[0].buf, lpBuffers[0].len,\r
+ send_wr.remote_ops.vaddr, send_wr.remote_ops.rkey) );\r
\r
fzprint(("posted RDMA %p, len=%d, op=%d, mr handle=%p\n",\r
lpOverlapped, lpBuffers[0].len, wr_type, node));\r
IN SIZE_T Size,\r
OUT LPINT lpErrno )\r
{\r
+ cl_list_item_t *p_item;\r
+\r
IBSP_ENTER( IBSP_DBG_MEM );\r
\r
- UNUSED_PARAM( lpvAddress );\r
- UNUSED_PARAM( Size );\r
UNUSED_PARAM( lpErrno );\r
\r
+ cl_spinlock_acquire( &g_ibsp.hca_mutex );\r
+ for( p_item = cl_qlist_head( &g_ibsp.hca_list );\r
+ p_item != cl_qlist_end( &g_ibsp.hca_list );\r
+ p_item = cl_qlist_next( p_item ) )\r
+ {\r
+ ibsp_hca_flush_mr_cache(\r
+ PARENT_STRUCT( p_item, struct ibsp_hca, item ), lpvAddress, Size );\r
+ }\r
+ cl_spinlock_release( &g_ibsp.hca_mutex );\r
+\r
IBSP_EXIT( IBSP_DBG_MEM );\r
return 0;\r
}\r
#include "ibspdll.h"\r
\r
\r
-/* Find the first registered mr that matches the given region. \r
- * mem_list is either socket_info->buf_mem_list or socket_info->rdma_mem_list.\r
- * mem_list_mutex must be taken.\r
- */\r
-static inline struct memory_node *\r
-__lookup_partial_mr(\r
- IN struct mr_list *mem_list,\r
+__forceinline boolean_t\r
+__check_mr(\r
+ IN struct memory_reg *p_reg,\r
IN ib_access_t acl_mask,\r
IN void *start,\r
IN size_t len )\r
{\r
- cl_list_item_t *item;\r
-\r
- for( item = cl_qlist_head( &mem_list->list );\r
- item != cl_qlist_end( &mem_list->list );\r
- item = cl_qlist_next( item ) )\r
- {\r
- struct memory_node *node = PARENT_STRUCT(item, struct memory_node, item);\r
-\r
- if( (node->type.access_ctrl & acl_mask) == acl_mask &&\r
- start >= node->type.vaddr &&\r
- ((unsigned char *)start) + len <=\r
- ((unsigned char * __ptr64)node->type.vaddr) + node->type.length )\r
- {\r
- return node;\r
- }\r
- }\r
-\r
- return NULL;\r
+ return( (p_reg->type.access_ctrl & acl_mask) == acl_mask &&\r
+ start >= p_reg->type.vaddr &&\r
+ ((uintn_t)start) + len <=\r
+ ((uintn_t)(uint64_t)p_reg->type.vaddr) + p_reg->type.length );\r
}\r
\r
\r
*/\r
struct memory_node *\r
lookup_partial_mr(\r
- IN struct mr_list *mem_list,\r
+ IN struct ibsp_socket_info *s,\r
IN ib_access_t acl_mask,\r
IN void *start,\r
IN size_t len )\r
{\r
- struct memory_node *node;\r
+ struct memory_node *p_node;\r
+ cl_list_item_t *p_item;\r
\r
IBSP_ENTER( IBSP_DBG_MEM );\r
\r
- cl_spinlock_acquire( &mem_list->mutex );\r
-\r
- node = __lookup_partial_mr( mem_list, acl_mask, start, len );\r
+ cl_spinlock_acquire( &s->port->hca->rdma_mem_list.mutex );\r
\r
- cl_spinlock_release( &mem_list->mutex );\r
+ for( p_item = cl_qlist_head( &s->mr_list );\r
+ p_item != cl_qlist_end( &s->mr_list );\r
+ p_item = cl_qlist_next( p_item ) )\r
+ {\r
+ p_node = PARENT_STRUCT( p_item, struct memory_node, socket_item );\r
+ \r
+ if( __check_mr( p_node->p_reg, acl_mask, start, len ) )\r
+ {\r
+ cl_spinlock_release( &s->port->hca->rdma_mem_list.mutex );\r
+ IBSP_EXIT( IBSP_DBG_MEM );\r
+ return p_node;\r
+ }\r
+ }\r
\r
- if( node )\r
- IBSP_EXIT( IBSP_DBG_MEM );\r
- else\r
- IBSP_TRACE_EXIT( IBSP_DBG_MEM, ("mr not found\n") );\r
+ cl_spinlock_release( &s->port->hca->rdma_mem_list.mutex );\r
\r
- return node;\r
+ IBSP_TRACE_EXIT( IBSP_DBG_MEM, ("mr not found\n") );\r
+ return NULL;\r
}\r
\r
\r
* mem_list is either socket_info->buf_mem_list or hca->rdma_mem_list.\r
*/\r
struct memory_node *\r
-ib_register_memory(\r
- IN struct mr_list *mem_list,\r
+ibsp_reg_mem(\r
+ IN struct ibsp_socket_info *s,\r
IN ib_pd_handle_t pd,\r
IN void *start,\r
IN size_t len,\r
IN ib_access_t access_ctrl,\r
OUT LPINT lpErrno )\r
{\r
- struct memory_node *node;\r
- ib_api_status_t status;\r
+ struct memory_node *p_node;\r
+ struct memory_reg *p_reg;\r
+ cl_list_item_t *p_item;\r
+ ib_api_status_t status;\r
\r
IBSP_ENTER( IBSP_DBG_MEM );\r
\r
CL_ASSERT( (access_ctrl & ~(IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE)) ==\r
0 );\r
\r
- /* First, try to find a suitable MR */\r
- cl_spinlock_acquire( &mem_list->mutex );\r
+ /* Optimistically allocate a tracking structure. */\r
+ p_node = HeapAlloc( g_ibsp.heap, 0, sizeof(struct memory_node) );\r
+ if( !p_node )\r
+ {\r
+ IBSP_ERROR_EXIT(\r
+ ("AllocateOverlappedBuf:HeapAlloc() failed: %d\n",\r
+ GetLastError()) );\r
+ *lpErrno = WSAENOBUFS;\r
+ return NULL;\r
+ }\r
\r
- node = __lookup_partial_mr( mem_list, access_ctrl, start, len );\r
+ /* First, try to find a suitable MR */\r
+ cl_spinlock_acquire( &s->port->hca->rdma_mem_list.mutex );\r
\r
- if( node )\r
+ /* Find the first registered mr that matches the given region. */\r
+ for( p_item = cl_qlist_head( &s->port->hca->rdma_mem_list.list );\r
+ p_item != cl_qlist_end( &s->port->hca->rdma_mem_list.list );\r
+ p_item = cl_qlist_next( p_item ) )\r
{\r
- node->refcount++;\r
- cl_spinlock_release( &mem_list->mutex );\r
- IBSP_EXIT( IBSP_DBG_MEM );\r
- return node;\r
- }\r
+ p_reg = PARENT_STRUCT(p_item, struct memory_reg, item);\r
\r
- cl_spinlock_release( &mem_list->mutex );\r
+ if( __check_mr( p_reg, access_ctrl, start, len ) )\r
+ {\r
+ p_node->p_reg = p_reg;\r
+ p_node->s = s;\r
+ cl_qlist_insert_tail( &p_reg->node_list, &p_node->mr_item );\r
+ cl_qlist_insert_head(\r
+ &s->mr_list, &p_node->socket_item );\r
+ cl_spinlock_release( &s->port->hca->rdma_mem_list.mutex );\r
+ IBSP_EXIT( IBSP_DBG_MEM );\r
+ return p_node;\r
+ }\r
+ }\r
\r
/* No corresponding MR has been found. Create a new one. */\r
- node = HeapAlloc( g_ibsp.heap, 0, sizeof(struct memory_node) );\r
+ p_reg = HeapAlloc( g_ibsp.heap, 0, sizeof(struct memory_reg) );\r
\r
- if( node == NULL )\r
+ if( !p_reg )\r
{\r
IBSP_ERROR_EXIT(\r
("AllocateOverlappedBuf:HeapAlloc() failed: %d\n",\r
GetLastError()) );\r
+ cl_spinlock_release( &s->port->hca->rdma_mem_list.mutex );\r
+ HeapFree( g_ibsp.heap, 0, p_node );\r
*lpErrno = WSAENOBUFS;\r
return NULL;\r
}\r
\r
/* The node is not initialized yet. All the parameters given are\r
* supposed to be valid so we don't check them. */\r
- node->refcount = 1;\r
- node->type.vaddr = start;\r
- node->type.length = len;\r
- node->type.access_ctrl = access_ctrl;\r
+ cl_qlist_init( &p_reg->node_list );\r
+ p_reg->type.vaddr = start;\r
+ p_reg->type.length = len;\r
+ p_reg->type.access_ctrl = access_ctrl;\r
\r
- IBSP_TRACE2( IBSP_DBG_MEM, ("pinning memory node %p\n", node) );\r
- status = ib_reg_mem( pd, &node->type, &node->lkey, &node->rkey, &node->mr_handle );\r
+ IBSP_TRACE2( IBSP_DBG_MEM, ("pinning memory node %p\n", p_node) );\r
+ status = ib_reg_mem(\r
+ pd, &p_reg->type, &p_reg->lkey, &p_reg->rkey, &p_reg->mr_handle );\r
\r
if( status )\r
{\r
-#ifdef _DEBUG_\r
- memset( node, 0x2e, sizeof(struct memory_node) ); /* Poison */\r
-#endif\r
- if( HeapFree( g_ibsp.heap, 0, node ) == FALSE )\r
- {\r
- IBSP_ERROR(\r
- ("BAD: HeapFree failed (%d)\n", GetLastError()) );\r
- }\r
+ cl_spinlock_release( &s->port->hca->rdma_mem_list.mutex );\r
+ HeapFree( g_ibsp.heap, 0, p_reg );\r
+ HeapFree( g_ibsp.heap, 0, p_node );\r
\r
- IBSP_ERROR_EXIT( ("ib_reg_mem failed (%d)\n", status) );\r
+ IBSP_ERROR_EXIT(\r
+ ("ib_reg_mem returned %s\n", ib_get_err_str(status)) );\r
\r
*lpErrno = WSAEFAULT;\r
return NULL;\r
\r
STAT_INC( mr_num );\r
\r
+ p_node->p_reg = p_reg;\r
+ p_node->s = s;\r
+\r
/* Link to the list of nodes. */\r
- cl_spinlock_acquire( &mem_list->mutex );\r
- cl_qlist_insert_head( &mem_list->list, &node->item );\r
- cl_spinlock_release( &mem_list->mutex );\r
+ cl_qlist_insert_head( &s->port->hca->rdma_mem_list.list, &p_reg->item );\r
+ cl_qlist_insert_head( &s->mr_list, &p_node->socket_item );\r
+ cl_qlist_insert_tail( &p_reg->node_list, &p_node->mr_item );\r
+ cl_spinlock_release( &s->port->hca->rdma_mem_list.mutex );\r
\r
IBSP_EXIT( IBSP_DBG_MEM );\r
\r
*lpErrno = 0;\r
- return node;\r
+ return p_node;\r
+}\r
+\r
+\r
+static inline int __ibsp_dereg_mem_mr(\r
+ IN struct memory_node *node )\r
+{\r
+ IBSP_ENTER( IBSP_DBG_MEM );\r
+\r
+ cl_qlist_remove_item( &node->p_reg->node_list, &node->mr_item );\r
+ cl_qlist_remove_item( &node->s->mr_list, &node->socket_item );\r
+\r
+ HeapFree( g_ibsp.heap, 0, node );\r
+\r
+ IBSP_EXIT( IBSP_DBG_MEM );\r
+ return 0;\r
}\r
\r
\r
/* Deregisters a memory region */\r
int\r
-ib_deregister_memory(\r
- IN struct mr_list *mem_list,\r
+ibsp_dereg_mem(\r
+ IN struct ibsp_socket_info *s,\r
IN struct memory_node *node,\r
OUT LPINT lpErrno )\r
{\r
-#if 0\r
- ib_api_status_t status;\r
-#endif\r
+ IBSP_ENTER( IBSP_DBG_MEM );\r
+\r
+ cl_spinlock_acquire( &s->port->hca->rdma_mem_list.mutex );\r
+ *lpErrno = __ibsp_dereg_mem_mr( node );\r
+ cl_spinlock_release( &s->port->hca->rdma_mem_list.mutex );\r
+\r
+ IBSP_EXIT( IBSP_DBG_MEM );\r
+ return (*lpErrno? SOCKET_ERROR : 0);\r
+}\r
+\r
+\r
+/*\r
+ * Deregister the remaining memory regions on an HCA. This function should\r
+ * only be called before destroying the PD. In normal case, the list should\r
+ * be empty because the switch should have done it.\r
+ */\r
+void\r
+ibsp_dereg_hca(\r
+ IN struct mr_list *mem_list )\r
+{\r
+ cl_list_item_t *item;\r
\r
IBSP_ENTER( IBSP_DBG_MEM );\r
\r
cl_spinlock_acquire( &mem_list->mutex );\r
+ IBSP_TRACE1( IBSP_DBG_MEM,\r
+ ("%d registrations.\n", cl_qlist_count( &mem_list->list )) );\r
\r
- if( node->refcount <= 0 )\r
- {\r
- cl_spinlock_release( &mem_list->mutex );\r
- IBSP_ERROR(\r
- ("ib_deregister_memory: bad refcount %d)\n", node->refcount) );\r
- *lpErrno = WSAEINVAL;\r
- return SOCKET_ERROR;\r
- }\r
-#if 0\r
- if( --node->refcount == 0 )\r
+ for( item = cl_qlist_remove_head( &mem_list->list );\r
+ item != cl_qlist_end( &mem_list->list );\r
+ item = cl_qlist_remove_head( &mem_list->list ) )\r
{\r
- cl_qlist_remove_item( &mem_list->list, &node->item );\r
+ struct memory_reg *p_reg = PARENT_STRUCT(item, struct memory_reg, item);\r
+ ib_api_status_t status;\r
+\r
+ while( cl_qlist_count( &p_reg->node_list ) )\r
+ {\r
+ struct memory_node *p_node =\r
+ PARENT_STRUCT( cl_qlist_head( &p_reg->node_list ),\r
+ struct memory_node, mr_item );\r
\r
- status = ib_dereg_mr( node->mr_handle );\r
+ __ibsp_dereg_mem_mr( p_node );\r
+ }\r
+\r
+ IBSP_TRACE2( IBSP_DBG_MEM, ("unpinning ,memory reg %p\n", p_reg) );\r
+ status = ib_dereg_mr( p_reg->mr_handle );\r
if( status )\r
{\r
- IBSP_ERROR( ("ib_dereg_mr failed (%d)\n", status) );\r
+ IBSP_ERROR(\r
+ ("ib_dereg_mem returned %s\n", ib_get_err_str( status )) );\r
}\r
else\r
{\r
STAT_DEC( mr_num );\r
}\r
\r
-#ifdef _DEBUG_\r
- memset( node, 0x39, sizeof(struct memory_node) );\r
-#endif\r
- if( HeapFree( g_ibsp.heap, 0, node ) == FALSE )\r
- {\r
- IBSP_ERROR(\r
- ("BAD: HeapFree failed (%d)\n", GetLastError()) );\r
- }\r
+ HeapFree( g_ibsp.heap, 0, p_reg );\r
}\r
-#else\r
- /* Never deregister. Cache it. */\r
- --node->refcount;\r
-#endif\r
\r
cl_spinlock_release( &mem_list->mutex );\r
\r
IBSP_EXIT( IBSP_DBG_MEM );\r
-\r
- *lpErrno = 0;\r
- return 0;\r
}\r
\r
\r
/* Deregister the remaining memory regions. This function should only \r
- * be called before destroying the PD. In normal case, the list should \r
+ * be called when destroying the socket. In normal case, the list should \r
* be empty because the switch should have done it. */\r
void\r
-ib_deregister_all_mr(\r
- IN struct mr_list *mem_list )\r
+ibsp_dereg_socket(\r
+ IN struct ibsp_socket_info *s )\r
{\r
- cl_list_item_t *item;\r
-\r
IBSP_ENTER( IBSP_DBG_MEM );\r
\r
- cl_spinlock_acquire( &mem_list->mutex );\r
+ if( !s->port )\r
+ {\r
+ CL_ASSERT( !cl_qlist_count( &s->mr_list ) );\r
+ IBSP_EXIT( IBSP_DBG_MEM );\r
+ return;\r
+ }\r
+\r
+ cl_spinlock_acquire( &s->port->hca->rdma_mem_list.mutex );\r
IBSP_TRACE1( IBSP_DBG_MEM,\r
- ("%d registrations.\n", cl_qlist_count( &mem_list->list )) );\r
+ ("%d registrations.\n", cl_qlist_count( &s->mr_list )) );\r
\r
- while( (item = cl_qlist_remove_head( &mem_list->list )) != cl_qlist_end( &mem_list->list ) )\r
+ while( cl_qlist_count( &s->mr_list ) )\r
{\r
- struct memory_node *node = PARENT_STRUCT(item, struct memory_node, item);\r
- ib_api_status_t status;\r
+ __ibsp_dereg_mem_mr( PARENT_STRUCT( cl_qlist_head( &s->mr_list ),\r
+ struct memory_node, socket_item) );\r
+ }\r
\r
- IBSP_TRACE2( IBSP_DBG_MEM, ("unpinning ,memory node node %p\n", node) );\r
- status = ib_dereg_mr( node->mr_handle );\r
- if( status )\r
+ cl_spinlock_release( &s->port->hca->rdma_mem_list.mutex );\r
+\r
+ IBSP_EXIT( IBSP_DBG_MEM );\r
+}\r
+\r
+\r
+/*\r
+ * Loop through all the memory registrations on an HCA and release\r
+ * all that fall within the specified range.\r
+ */\r
+void\r
+ibsp_hca_flush_mr_cache(\r
+ IN struct ibsp_hca *p_hca,\r
+ IN LPVOID lpvAddress,\r
+ IN SIZE_T Size )\r
+{\r
+ struct memory_reg *p_reg;\r
+ cl_list_item_t *p_item;\r
+ ib_api_status_t status;\r
+\r
+ IBSP_ENTER( IBSP_DBG_MEM );\r
+\r
+ cl_spinlock_acquire( &p_hca->rdma_mem_list.mutex );\r
+ for( p_item = cl_qlist_head( &p_hca->rdma_mem_list.list );\r
+ p_item != cl_qlist_end( &p_hca->rdma_mem_list.list );\r
+ p_item = cl_qlist_next( p_item ) )\r
+ {\r
+ p_reg = PARENT_STRUCT( p_item, struct memory_reg, item );\r
+\r
+ if( lpvAddress > p_reg->type.vaddr ||\r
+ ((uintn_t)lpvAddress) + Size <\r
+ ((uintn_t)(uint64_t)p_reg->type.vaddr) + p_reg->type.length )\r
{\r
- IBSP_ERROR(\r
- ("ib_dereg_mem returned %s\n", ib_get_err_str( status )) );\r
+ continue;\r
}\r
- else\r
+\r
+ /* Release all socket's nodes that reference this registration. */\r
+ while( cl_qlist_count( &p_reg->node_list ) )\r
{\r
- STAT_DEC( mr_num );\r
+ struct memory_node *p_node =\r
+ PARENT_STRUCT( cl_qlist_head( &p_reg->node_list ),\r
+ struct memory_node, mr_item );\r
+\r
+ __ibsp_dereg_mem_mr( p_node );\r
}\r
\r
-#ifdef _DEBUG_\r
- memset( node, 0x2d, sizeof(struct memory_node) ); /* Poison */\r
-#endif\r
+ /* Move to the previous item so the for loop properly moves forward. */\r
+ p_item = cl_qlist_prev( p_item );\r
+\r
+ cl_qlist_remove_item( &p_hca->rdma_mem_list.list, &p_reg->item );\r
\r
- if( HeapFree( g_ibsp.heap, 0, node ) == FALSE )\r
+ status = ib_dereg_mr( p_reg->mr_handle );\r
+ if( status != IB_SUCCESS )\r
{\r
IBSP_ERROR(\r
- ("BAD: HeapFree failed (%d)\n", GetLastError()) );\r
+ ("ib_dereg_mr returned %s\n", ib_get_err_str(status)) );\r
}\r
- }\r
\r
- cl_spinlock_release( &mem_list->mutex );\r
+ HeapFree( g_ibsp.heap, 0, p_reg );\r
+ }\r
+ cl_spinlock_release( &p_hca->rdma_mem_list.mutex );\r
\r
IBSP_EXIT( IBSP_DBG_MEM );\r
}\r