From b708f7dea9f43043a7c75a28cffe3dc2753dee9f Mon Sep 17 00:00:00 2001 From: shefty Date: Wed, 23 Jul 2008 21:41:18 +0000 Subject: [PATCH] uvp/av: change create/modify calls to take SGID index The uvp requires the SGID index to create/modify address handles. Modify the API and UVPs to take the SGID index as input. This avoids the UVP needing to cache the CA attributes, which can lead to accessing a stale GID table. The SGID index is passed into the UVP through the resv1 field of the GRH. Signed-off-by: Sean Hefty git-svn-id: svn://openib.tc.cornell.edu/gen1@1444 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- trunk/core/al/user/ual_av.c | 56 ++++++++++- trunk/hw/mlx4/user/hca/mlx4.c | 7 +- trunk/hw/mlx4/user/hca/verbs.c | 150 +--------------------------- trunk/hw/mlx4/user/hca/verbs.h | 16 --- trunk/hw/mthca/user/mlnx_ual_av.c | 54 +--------- trunk/hw/mthca/user/mlnx_ual_ca.c | 85 +--------------- trunk/hw/mthca/user/mlnx_ual_data.h | 1 - trunk/inc/iba/ib_types.h | 2 +- trunk/inc/user/iba/ib_uvp.h | 8 +- 9 files changed, 71 insertions(+), 308 deletions(-) diff --git a/trunk/core/al/user/ual_av.c b/trunk/core/al/user/ual_av.c index 4d7bb4af..24669abf 100644 --- a/trunk/core/al/user/ual_av.c +++ b/trunk/core/al/user/ual_av.c @@ -46,6 +46,32 @@ #endif +static ib_api_status_t +ual_get_gid_index( + IN struct _al_ci_ca *p_ci_ca, + IN uint8_t port_num, + IN ib_gid_t *p_gid, + OUT uint16_t *p_index) +{ + ib_port_attr_t *p_port_attr; + ib_api_status_t status = IB_INVALID_GID; + uint16_t i; + + ci_ca_lock_attr( p_ci_ca ); + p_port_attr = &p_ci_ca->p_user_attr->p_port_attr[port_num]; + for( i = 0; i < p_port_attr->num_gids; i++ ) + { + if( !cl_memcmp(p_gid, &p_port_attr->p_gid_table[i], sizeof(ib_gid_t)) ) + { + *p_index = i; + status = IB_SUCCESS; + break; + } + } + ci_ca_unlock_attr( p_ci_ca ); + + return status; +} ib_api_status_t ual_create_av( @@ -58,16 +84,28 @@ ual_create_av( cl_status_t cl_status = CL_ERROR; ib_api_status_t status = IB_ERROR; uvp_interface_t uvp_intf = h_pd->obj.p_ci_ca->verbs.user_verbs; + ib_av_attr_t av_attr; + uint16_t index; AL_ENTER( AL_DBG_AV ); /* Clear the ioctl_buf */ cl_memclr( &ioctl_buf, sizeof(ioctl_buf) ); + av_attr = *p_av_attr; /* Pre call to the UVP library */ if( h_pd->h_ci_pd && uvp_intf.pre_create_av ) { + if( p_av_attr->grh_valid ) + { + status = ual_get_gid_index(h_pd->obj.p_ci_ca, av_attr.port_num, + &av_attr.grh.src_gid, &index); + if( status != IB_SUCCESS ) + goto out; + av_attr.grh.resv1 = index; + } + status = uvp_intf.pre_create_av( h_pd->h_ci_pd, - p_av_attr, &ioctl_buf.in.umv_buf, &h_av->h_ci_av ); + &av_attr, &ioctl_buf.in.umv_buf, &h_av->h_ci_av ); if( status != IB_SUCCESS ) { AL_EXIT( AL_DBG_AV ); @@ -98,6 +136,7 @@ ual_create_av( status, &h_av->h_ci_av, &ioctl_buf.out.umv_buf); } +out: AL_EXIT( AL_DBG_AV ); return status; } @@ -229,17 +268,29 @@ ual_modify_av( ib_api_status_t status = IB_ERROR; ib_av_t* p_av = (ib_av_t*) h_av; uvp_interface_t uvp_intf = p_av->obj.p_ci_ca->verbs.user_verbs; + ib_av_attr_t av_attr; + uint16_t index; AL_ENTER( AL_DBG_AV ); /* Clear the ioctl_buf */ cl_memclr( &ioctl_buf, sizeof(ioctl_buf) ); + av_attr = *p_av_attr; /* Call the uvp pre call if the vendor library provided a valid ca handle */ if( p_av->h_ci_av && uvp_intf.pre_modify_av ) { + if( p_av_attr->grh_valid ) + { + status = ual_get_gid_index(p_av->obj.p_ci_ca, av_attr.port_num, + &av_attr.grh.src_gid, &index); + if( status != IB_SUCCESS ) + goto out; + av_attr.grh.resv1 = index; + } + /* Pre call to the UVP library */ status = uvp_intf.pre_modify_av( p_av->h_ci_av, - p_av_attr, &ioctl_buf.in.umv_buf ); + &av_attr, &ioctl_buf.in.umv_buf ); if( status == IB_VERBS_PROCESSING_DONE ) { /* Modification is done in user mode. Issue the post call */ @@ -285,6 +336,7 @@ ual_modify_av( p_av->h_ci_av, status, &ioctl_buf.out.umv_buf ); } +out: AL_EXIT( AL_DBG_AV ); return status; } diff --git a/trunk/hw/mlx4/user/hca/mlx4.c b/trunk/hw/mlx4/user/hca/mlx4.c index 8f6b78d0..488d5d1e 100644 --- a/trunk/hw/mlx4/user/hca/mlx4.c +++ b/trunk/hw/mlx4/user/hca/mlx4.c @@ -154,7 +154,6 @@ found: GetSystemInfo(&sys_info); context->ibv_ctx.page_size = sys_info.dwPageSize; - context->ibv_ctx.p_hca_attr = NULL; return &context->ibv_ctx; @@ -175,8 +174,6 @@ void mlx4_free_context(struct ibv_context *ctx) CloseHandle(context->xrc_srq_table_mutex); #endif CloseHandle(context->qp_table_mutex); - if (context->ibv_ctx.p_hca_attr) - cl_free(context->ibv_ctx.p_hca_attr); cl_free(context); } @@ -184,8 +181,8 @@ static void __get_uvp_interface(uvp_interface_t *p_uvp) { p_uvp->pre_open_ca = mlx4_pre_open_ca; p_uvp->post_open_ca = mlx4_post_open_ca; - p_uvp->pre_query_ca = mlx4_pre_query_ca; - p_uvp->post_query_ca = mlx4_post_query_ca; + p_uvp->pre_query_ca = NULL; + p_uvp->post_query_ca = NULL; p_uvp->pre_modify_ca = NULL; p_uvp->post_modify_ca = NULL; p_uvp->pre_close_ca = NULL; diff --git a/trunk/hw/mlx4/user/hca/verbs.c b/trunk/hw/mlx4/user/hca/verbs.c index e7c6b4ea..8dd08da1 100644 --- a/trunk/hw/mlx4/user/hca/verbs.c +++ b/trunk/hw/mlx4/user/hca/verbs.c @@ -105,102 +105,6 @@ end: return status; } -ib_api_status_t -mlx4_pre_query_ca ( - IN ib_ca_handle_t h_uvp_ca, - IN ib_ca_attr_t *p_ca_attr, - IN size_t byte_count, - IN ci_umv_buf_t *p_umv_buf ) -{ - ib_api_status_t status = IB_SUCCESS; - - UNREFERENCED_PARAMETER(h_uvp_ca); - - /* Note that query_ca calls *always* get their attributes from the kernel. - * - * Assume if user buffer is valid then byte_cnt is valid too - * so we can preallocate ca attr buffer for post ioctl data saving - * - * Note that we squirrel the buffer away into the umv_buf and only - * set it into the HCA if the query is successful. - */ - if ( p_ca_attr != NULL ) - { - p_umv_buf->p_inout_buf = (ULONG_PTR)cl_malloc(byte_count); - if ( !p_umv_buf->p_inout_buf ) - { - status = IB_INSUFFICIENT_RESOURCES; - goto end; - } - } - -end: - return status; -} - -void -__fixup_ca_attr( - IN ib_ca_attr_t* const p_dest, - IN const ib_ca_attr_t* const p_src ) -{ - uint8_t i; - uintn_t offset = (uintn_t)p_dest - (uintn_t)p_src; - ib_port_attr_t *p_tmp_port_attr = NULL; - - CL_ASSERT( p_dest ); - CL_ASSERT( p_src ); - - /* Fix up the pointers to point within the destination buffer. */ - p_dest->p_page_size = - (uint32_t*)(((uint8_t*)p_dest->p_page_size) + offset); - - p_tmp_port_attr = - (ib_port_attr_t*)(((uint8_t*)p_dest->p_port_attr) + offset); - - /* Fix up each port attribute's gid and pkey table pointers. */ - for( i = 0; i < p_dest->num_ports; i++ ) - { - p_tmp_port_attr[i].p_gid_table = (ib_gid_t*) - (((uint8_t*)p_tmp_port_attr[i].p_gid_table) + offset); - - p_tmp_port_attr[i].p_pkey_table =(ib_net16_t*) - (((uint8_t*)p_tmp_port_attr[i].p_pkey_table) + offset); - } - p_dest->p_port_attr = p_tmp_port_attr; -} - -void -mlx4_post_query_ca ( - IN ib_ca_handle_t h_uvp_ca, - IN ib_api_status_t ioctl_status, - IN ib_ca_attr_t *p_ca_attr, - IN size_t byte_count, - IN ci_umv_buf_t *p_umv_buf ) -{ - struct ibv_context *context = (struct ibv_context *)h_uvp_ca; - - CL_ASSERT(context && p_umv_buf); - - if ( ioctl_status == IB_SUCCESS && p_ca_attr && byte_count) - { - CL_ASSERT( byte_count >= p_ca_attr->size ); - - pthread_mutex_lock(&context->mutex); - - if (context->p_hca_attr) - cl_free(context->p_hca_attr); - context->p_hca_attr = (ib_ca_attr_t*)(ULONG_PTR)p_umv_buf->p_inout_buf; - cl_memcpy( context->p_hca_attr, p_ca_attr, p_ca_attr->size ); - __fixup_ca_attr( context->p_hca_attr, p_ca_attr ); - - pthread_mutex_unlock(&context->mutex); - } - else if (p_umv_buf->p_inout_buf) - { - cl_free( (void*)(ULONG_PTR)p_umv_buf->p_inout_buf ); - } -} - ib_api_status_t mlx4_post_close_ca ( IN ib_ca_handle_t h_uvp_ca, @@ -1131,32 +1035,6 @@ mlx4_nd_get_qp_state ( return __from_qp_state(ibv_qp->state); } -static uint8_t -__gid_to_index_lookup ( - IN ib_ca_attr_t *p_ca_attr, - IN uint8_t port_num, - IN uint8_t *raw_gid ) -{ - ib_gid_t *p_gid_table = NULL; - uint8_t i, index = 0; - uint16_t num_gids; - - p_gid_table = p_ca_attr->p_port_attr[port_num-1].p_gid_table; - CL_ASSERT (p_gid_table); - - num_gids = p_ca_attr->p_port_attr[port_num-1].num_gids; - - for (i = 0; i < num_gids; i++) - { - if (cl_memcmp (raw_gid, p_gid_table[i].raw, 16)) - { - index = i; - break; - } - } - return index; -} - static enum ibv_rate __to_rate(uint8_t rate) { if (rate == IB_PATH_RECORD_RATE_2_5_GBS) return IBV_RATE_2_5_GBPS; @@ -1194,17 +1072,9 @@ __grh_get_ver_class_flow( static ib_api_status_t __to_ah ( - IN ib_ca_attr_t *p_ca_attr, IN const ib_av_attr_t *p_av_attr, OUT struct ibv_ah_attr *p_attr ) { - if (p_av_attr->port_num == 0 || - p_av_attr->port_num > p_ca_attr->num_ports) { - MLX4_PRINT(TRACE_LEVEL_WARNING ,MLX4_DBG_AV , - (" invalid port number specified (%d)\n",p_av_attr->port_num)); - return IB_INVALID_PORT; - } - p_attr->port_num = p_av_attr->port_num; p_attr->sl = p_av_attr->sl; p_attr->dlid = cl_ntoh16 (p_av_attr->dlid); @@ -1218,8 +1088,7 @@ __to_ah ( p_attr->grh.hop_limit = p_av_attr->grh.hop_limit; __grh_get_ver_class_flow( p_av_attr->grh.ver_class_flow, NULL, &p_attr->grh.traffic_class, &p_attr->grh.flow_label ); - p_attr->grh.sgid_index = __gid_to_index_lookup (p_ca_attr, p_av_attr->port_num, - (uint8_t *) p_av_attr->grh.src_gid.raw); + p_attr->grh.sgid_index = (uint8_t) p_av_attr->grh.resv1; cl_memcpy (p_attr->grh.dgid.raw, p_av_attr->grh.dest_gid.raw, 16); } else @@ -1266,28 +1135,15 @@ mlx4_pre_create_ah ( UNREFERENCED_PARAMETER(p_umv_buf); - if (pd->context->p_hca_attr == NULL) { - status = IB_ERROR; - goto end; - } - ah = cl_malloc(sizeof *ah); if (!ah) { status = IB_INSUFFICIENT_MEMORY; goto end; } - // sanity check - if (p_av_attr->port_num == 0 || - p_av_attr->port_num > pd->context->p_hca_attr->num_ports) - { - status = IB_INVALID_PORT; - goto end; - } - // convert parameters cl_memset(&attr, 0, sizeof(attr)); - status = __to_ah(pd->context->p_hca_attr, p_av_attr, &attr); + status = __to_ah(p_av_attr, &attr); if (status) goto end; @@ -1352,7 +1208,7 @@ mlx4_pre_modify_ah ( CL_ASSERT (h_uvp_av); - status = __to_ah(ah->context->p_hca_attr, p_addr_vector, &attr); + status = __to_ah(p_addr_vector, &attr); if (status) return status; diff --git a/trunk/hw/mlx4/user/hca/verbs.h b/trunk/hw/mlx4/user/hca/verbs.h index fbef971c..85c9551e 100644 --- a/trunk/hw/mlx4/user/hca/verbs.h +++ b/trunk/hw/mlx4/user/hca/verbs.h @@ -209,7 +209,6 @@ struct ibv_ah { }; struct ibv_context { - ib_ca_attr_t *p_hca_attr; int page_size; pthread_mutex_t mutex; }; @@ -229,21 +228,6 @@ mlx4_post_open_ca ( IN OUT ib_ca_handle_t *ph_uvp_ca, IN ci_umv_buf_t *p_umv_buf ); -ib_api_status_t -mlx4_pre_query_ca ( - IN ib_ca_handle_t h_uvp_ca, - IN ib_ca_attr_t *p_ca_attr, - IN size_t byte_count, - IN ci_umv_buf_t *p_umv_buf ); - -void -mlx4_post_query_ca ( - IN ib_ca_handle_t h_uvp_ca, - IN ib_api_status_t ioctl_status, - IN ib_ca_attr_t *p_ca_attr, - IN size_t byte_count, - IN ci_umv_buf_t *p_umv_buf ); - ib_api_status_t mlx4_post_close_ca ( IN ib_ca_handle_t h_uvp_ca, diff --git a/trunk/hw/mthca/user/mlnx_ual_av.c b/trunk/hw/mthca/user/mlnx_ual_av.c index d3a76fc6..6e913d2d 100644 --- a/trunk/hw/mthca/user/mlnx_ual_av.c +++ b/trunk/hw/mthca/user/mlnx_ual_av.c @@ -48,51 +48,12 @@ __post_create_av ( IN OUT ci_umv_buf_t *p_umv_buf); -uint8_t -gid_to_index_lookup ( - IN ib_ca_attr_t *p_ca_attr, - IN uint8_t port_num, - IN uint8_t *raw_gid) -{ - ib_gid_t *p_gid_table = NULL; - uint8_t i, index = 0; - uint16_t num_gids; - - p_gid_table = p_ca_attr->p_port_attr[port_num-1].p_gid_table; - CL_ASSERT (p_gid_table); - - num_gids = p_ca_attr->p_port_attr[port_num-1].num_gids; - UVP_PRINT(TRACE_LEVEL_INFORMATION, UVP_DBG_AV, - ("Port %d has %d gids\n", port_num, num_gids)); - - for (i = 0; i < num_gids; i++) - { - if (cl_memcmp (raw_gid, p_gid_table[i].raw, sizeof (ib_gid_t))) - { - UVP_PRINT(TRACE_LEVEL_INFORMATION ,UVP_DBG_AV , - ("found GID at index %d\n", i)); - index = i; - break; - } - } - return index; -} - ib_api_status_t map_itom_av_attr ( - IN ib_ca_attr_t *p_ca_attr, IN const ib_av_attr_t *p_av_attr, OUT struct ibv_ah_attr *p_attr) { - - ib_api_status_t status = IB_SUCCESS; - if (p_av_attr->port_num == 0 || - p_av_attr->port_num > p_ca_attr->num_ports) { - UVP_PRINT(TRACE_LEVEL_WARNING ,UVP_DBG_AV , - (" invalid port number specified (%d)\n",p_av_attr->port_num)); - return IB_INVALID_PORT; - } p_attr->sl = p_av_attr->sl; p_attr->port_num = p_av_attr->port_num; @@ -109,8 +70,7 @@ map_itom_av_attr ( p_attr->grh.hop_limit = p_av_attr->grh.hop_limit; ib_grh_get_ver_class_flow( p_av_attr->grh.ver_class_flow, NULL, &p_attr->grh.traffic_class, &p_attr->grh.flow_label ); - p_attr->grh.sgid_index = gid_to_index_lookup (p_ca_attr, - p_av_attr->port_num, (uint8_t *) p_av_attr->grh.src_gid.raw); + p_attr->grh.sgid_index = (uint8_t) p_av_attr->grh.resv1; cl_memcpy (p_attr->grh.dgid.raw, p_av_attr->grh.dest_gid.raw, sizeof (IB_gid_t)); }else{ @@ -142,17 +102,9 @@ __pre_create_av ( CL_ASSERT(p_umv_buf); - // sanity check - if (p_av_attr->port_num == 0 || p_av_attr->port_num > p_hobul->p_hca_attr->num_ports) { - UVP_PRINT(TRACE_LEVEL_WARNING ,UVP_DBG_AV , - (" invalid port number specified (%d)\n",p_av_attr->port_num)); - status = IB_INVALID_PORT; - goto end; - } - // convert parameters cl_memset( &attr, 0, sizeof(attr)); - status = map_itom_av_attr (p_hobul->p_hca_attr, p_av_attr, &attr); + status = map_itom_av_attr (p_av_attr, &attr); if(status != IB_SUCCESS ) goto end; @@ -328,7 +280,7 @@ __pre_modify_av ( p_hobul = p_pd_info->p_hobul; CL_ASSERT (p_hobul); - status = map_itom_av_attr (p_hobul->p_hca_attr, p_addr_vector, &attr); + status = map_itom_av_attr (p_addr_vector, &attr); if(status != IB_SUCCESS) return status; mthca_set_av_params( mthca_ah, &attr); diff --git a/trunk/hw/mthca/user/mlnx_ual_ca.c b/trunk/hw/mthca/user/mlnx_ual_ca.c index dc731696..4cea6bd1 100644 --- a/trunk/hw/mthca/user/mlnx_ual_ca.c +++ b/trunk/hw/mthca/user/mlnx_ual_ca.c @@ -107,7 +107,6 @@ __post_open_ca ( /* return results */ new_ca->ibv_ctx = ibvcontext; - new_ca->p_hca_attr = NULL; *ph_uvp_ca = (ib_ca_handle_t)new_ca; } @@ -119,81 +118,6 @@ err_alloc_context: return status; } -static ib_api_status_t -__pre_query_ca ( - IN ib_ca_handle_t h_uvp_ca, - IN ib_ca_attr_t *p_ca_attr, - IN size_t byte_count, - IN ci_umv_buf_t *p_umv_buf ) -{ - ib_api_status_t status = IB_SUCCESS; - - UVP_ENTER(UVP_DBG_SHIM); - - CL_ASSERT(h_uvp_ca); - - /* - * First time call query_ca - populate our internal cached attributes - * so we can access the GID table. Note that query_ca calls *always* - * get their attributes from the kernel. - */ - if ( !h_uvp_ca->p_hca_attr ) - { - /* - * Assume if user buffer is valid then byte_cnt is valid too - * so we can preallocate ca attr buffer for post ioctl data saving - * - * Note that we squirel the buffer away into the umv_buf and only - * set it into the HCA if the query is successful. - */ - if ( p_ca_attr != NULL ) - { - p_umv_buf->p_inout_buf = (ULONG_PTR)cl_zalloc(byte_count); - if ( !p_umv_buf->p_inout_buf ) - { - UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_SHIM , - ("Failed to alloc new_ca\n")); - status = IB_INSUFFICIENT_RESOURCES; - return status; - } - } - p_umv_buf->input_size = p_umv_buf->output_size = 0; - } - - UVP_EXIT(UVP_DBG_SHIM); - return status; -} - - -static void -__post_query_ca ( - IN ib_ca_handle_t h_uvp_ca, - IN ib_api_status_t ioctl_status, - IN ib_ca_attr_t *p_ca_attr, - IN size_t byte_count, - IN ci_umv_buf_t *p_umv_buf ) -{ - UVP_ENTER(UVP_DBG_SHIM); - - CL_ASSERT(h_uvp_ca); - CL_ASSERT(p_umv_buf); - - if ( ioctl_status == IB_SUCCESS && p_ca_attr && - byte_count && !h_uvp_ca->p_hca_attr ) - { - CL_ASSERT( byte_count >= p_ca_attr->size ); - h_uvp_ca->p_hca_attr = (ib_ca_attr_t*)(ULONG_PTR)p_umv_buf->p_inout_buf; - ib_copy_ca_attr( h_uvp_ca->p_hca_attr, p_ca_attr ); - } - else if (p_umv_buf->p_inout_buf) - { - cl_free( (void*)(ULONG_PTR)p_umv_buf->p_inout_buf ); - } - - UVP_EXIT(UVP_DBG_SHIM); - return; -} - static ib_api_status_t __pre_modify_ca ( @@ -245,11 +169,6 @@ __post_close_ca ( p_hobul->ibv_ctx = NULL; } - if (p_hobul->p_hca_attr) { - cl_free( p_hobul->p_hca_attr); - p_hobul->p_hca_attr = NULL; - } - cl_free(p_hobul); } @@ -270,8 +189,8 @@ mlnx_get_ca_interface ( p_uvp->post_open_ca = __post_open_ca; - p_uvp->pre_query_ca = __pre_query_ca; - p_uvp->post_query_ca = __post_query_ca; + p_uvp->pre_query_ca = NULL; + p_uvp->post_query_ca = NULL; p_uvp->pre_modify_ca = NULL; p_uvp->post_modify_ca = NULL; diff --git a/trunk/hw/mthca/user/mlnx_ual_data.h b/trunk/hw/mthca/user/mlnx_ual_data.h index 2c646328..d57d4b07 100644 --- a/trunk/hw/mthca/user/mlnx_ual_data.h +++ b/trunk/hw/mthca/user/mlnx_ual_data.h @@ -41,7 +41,6 @@ typedef uint32_t IB_ts_t; typedef struct _ib_ca { struct ibv_context *ibv_ctx; - ib_ca_attr_t *p_hca_attr; } mlnx_ual_hobul_t; diff --git a/trunk/inc/iba/ib_types.h b/trunk/inc/iba/ib_types.h index 16bed5de..651dae9f 100644 --- a/trunk/inc/iba/ib_types.h +++ b/trunk/inc/iba/ib_types.h @@ -6461,7 +6461,7 @@ typedef struct _ib_vl_arb_table_record typedef struct _ib_grh { ib_net32_t ver_class_flow; - ib_net16_t resv1; + uint16_t resv1; uint8_t resv2; uint8_t hop_limit; ib_gid_t src_gid; diff --git a/trunk/inc/user/iba/ib_uvp.h b/trunk/inc/user/iba/ib_uvp.h index ed0283f9..cc159686 100644 --- a/trunk/inc/user/iba/ib_uvp.h +++ b/trunk/inc/user/iba/ib_uvp.h @@ -798,7 +798,9 @@ typedef ib_api_status_t * [in] Vendor's user-mode library handle to the Protection domain * to which this AV is associated. * p_addr_vector -* [in] Parameters to create the address vector. +* [in] Parameters to create the address vector. If the grh of the +* address vector is valid, then the grh resv1 field should be set to +* the index of the src_gid. * p_umv_buf * [in out] On input, UAL provides this buffer template. * On return from this function, p_umv_buf contains @@ -991,7 +993,9 @@ typedef ib_api_status_t * h_uvp_av * [in] Vendor's AV handle in user-mode library. * p_addr_vector -* [in] Parameters to modify the address vector handle +* [in] Parameters to modify the address vector handle. If the grh of the +* address vector is valid, then the grh resv1 field should be set to +* the index of the src_gid. * p_umv_buf * [in out] On input, UAL provides this buffer template. * On return from this function, p_umv_buf contains -- 2.46.0